복붙노트

[SPRING] 봄 부팅으로 프로그래밍 방식으로 스프링 변환기 등록

SPRING

봄 부팅으로 프로그래밍 방식으로 스프링 변환기 등록

스프링 부트 프로젝트에 스프링 변환기를 프로그래밍 방식으로 등록하려고합니다. 지난 봄 프로젝트에서 저는 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>

스프링 부트의 SpringBootServletInitializer에서 수행하는 방법을 파악하려고합니다.

업데이트 : StringToAssessmentConverter를 getConversionService의 인수로 전달하여 약간의 진전을 이루었습니다. 그러나 이제 StringToAssessmentConverter 클래스에 대해 "기본 생성자가 없습니다"오류가 발생합니다. 왜 Spring이 @Autowired 생성자를 보지 못하고 있는지 모르겠습니다.

@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. ==============================

    1.대답은 변환기를 @Component로 주석 달기 만하면됩니다.

    대답은 변환기를 @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());
        }
    }
    

    그리고 나서 Spring이 변환을해야 할 때, 변환기가 호출된다.

    내 봄 부팅 버전 : 1.4.1

  2. ==============================

    2.여기 내 해결책은 다음과 같습니다.

    여기 내 해결책은 다음과 같습니다.

    TypeConverter 주석 :

    @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());
            }
        }
    }
    
  3. ==============================

    3.이 시도:

    이 시도:

    @SpringBootApplication
    public class Application extends SpringBootServletInitializer {
    
        @Bean
        public AssessmentService assessmentService(){
            return new AssessmentService();
        }
    
        @Bean
        public StringToAssessmentConverter stringToAssessmentConverter(){
            return new StringToAssessmentConverter(assessmentService());
        }
    
        @Bean(name="conversionService")
        public ConversionService getConversionService() {
            ConversionServiceFactoryBean bean = new ConversionServiceFactoryBean();    
            Set<Converter> converters = new HashSet<Converter>();
    
            //add the converter
            converters.add(stringToAssessmentConverter()); 
    
            bean.setConverters(converters);
            return bean.getObject();
        }
    
        // separate these class into its own java file if necessary
        // Assesment service
        class AssessmentService {}
    
        //converter
        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;
                 }
             }
    
         }
    }
    

    또는 StringToAssessmentConverter가 이미 스프링 빈인 경우 :

    @Autowired
    @Bean(name="conversionService")
    public ConversionService getConversionService(StringToAssessmentConverter stringToAssessmentConverter) {
        ConversionServiceFactoryBean bean = new ConversionServiceFactoryBean();    
        Set<Converter> converters = new HashSet<Converter>();
    
        //add the converter
        converters.add(stringToAssessmentConverter); 
    
        bean.setConverters(converters);
        return bean.getObject();
    }
    
  4. from https://stackoverflow.com/questions/35025550/register-spring-converter-programmatically-in-spring-boot by cc-by-sa and MIT license