在弹簧启动中以编程方式注册弹簧转换器

2022-09-02 02:23:09

我想以编程方式在Spring Boot项目中注册Spring Converter。在过去的春季项目中,我用XML完成了它,就像这样...

<!-- Custom converters to allow automatic binding from Http requests parameters to objects -->
<!-- All converters are annotated w/@Component -->
<bean id="conversionService"
      class="org.springframework.context.support.ConversionServiceFactoryBean">
    <property name="converters">
        <list>
            <ref bean="stringToAssessmentConverter" />
        </list>
    </property>
</bean>

我试图弄清楚如何在Spring Boot的SpringBootServlet初始化器中做

更新:通过将 StringToAssessmentConverter 作为参数传递给 ,我取得了一些进展,但现在我收到了 StringToAssessmentConverter 类的错误。我不确定为什么Spring没有看到构造函数@Autowired。getConversionService"No default constructor found"

@SpringBootApplication
public class Application extends SpringBootServletInitializer {

    ...

    @Bean(name="conversionService")
    public ConversionServiceFactoryBean getConversionService(StringToAssessmentConverter stringToAssessmentConverter) {
        ConversionServiceFactoryBean bean = new ConversionServiceFactoryBean();

        Set<Converter> converters = new HashSet<>();

        converters.add(stringToAssessmentConverter);

        bean.setConverters(converters);
        return bean;
    }
}  

这是转换器的代码...

 @Component
 public class StringToAssessmentConverter implements Converter<String, Assessment> {

     private AssessmentService assessmentService;

     @Autowired
     public StringToAssessmentConverter(AssessmentService assessmentService) {
         this.assessmentService = assessmentService;
     }

     public Assessment convert(String source) {
         Long id = Long.valueOf(source);
         try {
             return assessmentService.find(id);
         } catch (SecurityException ex) {
             return null;
         }
     }
 }

完整错误

Failed to execute goal org.springframework.boot:spring-boot-maven-
plugin:1.3.2.RELEASE:run (default-cli) on project yrdstick: An exception 
occurred while running. null: InvocationTargetException: Error creating 
bean with name
'org.springframework.boot.context.properties.ConfigurationPropertiesBindingPo
stProcessor': Invocation of init method failed; nested exception is 
org.springframework.beans.factory.UnsatisfiedDependencyException: Error 
creating bean with name 'conversionService' defined in 
me.jpolete.yrdstick.Application: Unsatisfied dependency expressed through 
constructor argument with index 0 of type 
[me.jpolete.yrdstick.websupport.StringToAssessmentConverter]: : Error 
creating bean with name 'stringToAssessmentConverter' defined in file 
[/yrdstick/target/classes/me/jpolete/yrdstick/websupport
/StringToAssessmentConverter.class]: Instantiation of bean failed; nested 
exception is org.springframework.beans.BeanInstantiationException: Failed 
to instantiate 
[me.jpolete.yrdstick.websupport.StringToAssessmentConverter]: No default 
constructor found; nested exception is java.lang.NoSuchMethodException: 
me.jpolete.yrdstick.websupport.StringToAssessmentConverter.<init>(); 
nested exception is 
org.springframework.beans.factory.BeanCreationException: Error creating 
bean with name 'stringToAssessmentConverter' defined in file [/yrdstick
/dev/yrdstick/target/classes/me/jpolete/yrdstick/websupport
/StringToAssessmentConverter.class]: Instantiation of bean failed; nested 
exception is org.springframework.beans.BeanInstantiationException: Failed 
to instantiate 
[me.jpolete.yrdstick.websupport.StringToAssessmentConverter]: No default 
constructor found; nested exception is java.lang.NoSuchMethodException: 
me.jpolete.yrdstick.websupport.StringToAssessmentConverter.<init>()

答案 1

答案是,您只需要将转换器注释为:@Component

这是我的转换器示例

import org.springframework.core.convert.converter.Converter;
@Component
public class DateUtilToDateSQLConverter implements Converter<java.util.Date, Date> {

    @Override
    public Date convert(java.util.Date source) {
        return new Date(source.getTime());
    }
}

然后,当弹簧需要进行转换时,调用转换器。

我的弹簧靴版本:1.4.1


答案 2

这是我的解决方案:

类型转换器注释:

@Target({ElementType.TYPE, ElementType.FIELD, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface TypeConverter {
}

转换器注册器:

@Configuration
public class ConverterConfiguration {

    @Autowired(required = false)
    @TypeConverter
    private Set<Converter<?, ?>> autoRegisteredConverters;

    @Autowired(required = false)
    @TypeConverter
    private Set<ConverterFactory<?, ?>> autoRegisteredConverterFactories;

    @Autowired
    private ConverterRegistry converterRegistry;

    @PostConstruct
    public void conversionService() {
        if (autoRegisteredConverters != null) {
            for (Converter<?, ?> converter : autoRegisteredConverters) {
                converterRegistry.addConverter(converter);
            }
        }
        if (autoRegisteredConverterFactories != null) {
            for (ConverterFactory<?, ?> converterFactory : autoRegisteredConverterFactories) {
                converterRegistry.addConverterFactory(converterFactory);
            }
        }
    }

}

然后注释您的转换器:

@SuppressWarnings("rawtypes")
@TypeConverter
public class StringToEnumConverterFactory implements ConverterFactory<String, Enum> {

    @SuppressWarnings("unchecked")
    public <T extends Enum> Converter<String, T> getConverter(Class<T> targetType) {
        return new StringToEnum(targetType);
    }

    private final class StringToEnum<T extends Enum> implements Converter<String, T> {

        private Class<T> enumType;

        public StringToEnum(Class<T> enumType) {
            this.enumType = enumType;
        }

        @SuppressWarnings("unchecked")
        public T convert(String source) {
            return (T) Enum.valueOf(this.enumType, source.trim().toUpperCase());
        }
    }
}

推荐