====== Springframework Java Config ====== * Spring 3.1 부터 본격적으로 도입됨. * [[springframework:bean|SpringFramework Bean]] ===== 컨텍스트 클래스 ===== * [[http://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/context/annotation/AnnotationConfigApplicationContext.html|AnnotationConfigApplicationContext]] ===== 메소드 인자를 통한 주입 받기 ===== * 한 @Configuration 클래스안에서 FactoryBean으로 생성한 Bean과 그것을 주입 받는 빈이 있을 때, 메소드 직접 호출을 통한 주입이 애매하다. 빈을 생성하는 메소드를 직접 호출하면 FactoryBean 객체가 리턴되기 때문이다. * 이 때, @Bean 메소드의 인자로 FactoryBean 이 생성한 객체를 주입 받으면 된다. * **@Bean이 붙은 메소드는 기본적으로 @Autowired가 붙은 메소드 처럼 동작한다.** - 토비의 스프링 3.1 Vol 2. 135 페이지 * ''@Qualifier''를 파라미터에 추가해도 된다. * 한 메소드에서 여러개를 파라미터로 주입 받아도 된다. * 꼭, 현재 Configuration 클래스가 아닌 다른 곳에서 생성된 Bean도 주입 받을 수 있다. @Bean public Printer printer() { return new Printer(); } @Bean public Hello hello(Printer printer) { // 위에 선언된 printer Bean이 주입됨. ... hello.setPrinter(printer); } ===== @Primary ===== * [[http://docs.spring.io/spring/docs/3.2.x/javadoc-api/org/springframework/context/annotation/Primary.html|@Primary]] ===== 주의할 점 ===== ==== Java Config 클래스는 무조건 @Configuration 애노테이션을 붙인다 ==== Java Config용 클래스에 ''@Configuration''을 붙이지 않으면 ''@Bean'' 애노테이션된 메소드에 의한 객체 생성시 **싱글턴이 보장되지 않는다**. 또한 동일 설정 클래스에서 생성한 다른 Bean의 ''@Autowired'' 주입도 안 된다. ==== Spring의 특정 인터페이스를 구현했을 경우 처리 ==== Bean에 주입할 객체를 ''@Bean''으로 생성하지 않고 바로 new로 생성하여 주입하면 Spring의 InitializingBean과 같은 인터페이스를 구현한 것이 정상적으로 호출되지 않아 문제가 될 수 있다. 예) // WebMVC의 코드 중 일부 // 아래 코드에서 openEntityManagerInViewIterceptor는 BeanFactoryAware 인터페이스를 구현하고 있지만 // 해당 기능이 제대로 작동하지 않게 된다. OpenEntityManagerInViewInterceptor openEntityManagerInView = new OpenEntityManagerInViewInterceptor(); openEntityManagerInView.setEntityManagerFactory(entityManagerFactory); // ApplicationContext를 주입받아서 OEMIV 객체에 직접 주있해줬음. // 단, 항상 entityManagerFactory를 먼저 주입하고 다은에 applicationContext 주입할 것. // 안그러면 EMF가 여러개일 때 Autowiring 오류가 발생함. // 가장 좋은 것은 OEMIV를 직접 빈(''@Bean'')으로 생성하는 것. ==== @DependsOn ==== * Bean들간의 의존성 지정. ''@Component'', ''@Bean''과 함께 지정. * [[http://www.baeldung.com/spring-depends-on|Controlling Bean Creation Order with @DependsOn | Baeldung]] ==== Java Config간의 상호 의존 ==== ''XxxJavaConfig'' 클래스와 ''YyyJavaConfig''가 서로가 생성하는 객체를 주입받으려고 하면 문제가 된다. 현재 확인된 바로는 무한 루프를 도는 듯한 상황이 연출되었다. 이런 상황은 만들지 말 것. ==== 하나의 JavaConfig 안에서 Field를 통한 Properties 주입과 @Bean Properties 의 상호 의존 ==== * 하나의 JavaConfig안에서 Field에 ''@Value''로 주입하는 값이, 동일 설정 파일의 ''@Bean''을 통해 생성된 ''Properties'' 객체의 값일 때 **Circular Dependency**가 발생할 수도 있다. @Configuration public class SomePropsConfig { @Value("#{myProperties['myprops.someValue']}") private int someValue; public Properties myProperties() { return new Properties() ..... } } * 이 상황은 항상 발생하지는 않았고, 설정 파일이 여러개일 때 발생했다. * 가설 * 설정파일이 여러개일 때 ''SomePropsConfig'' 객체를 가진 설정파일보다 다른 설정파일이 먼저 로딩됨. * 해당 다른 설정파일이 ''SomePropsConfig'' 객체를 가진 설정파일에 있는 또 다른 제3의 Bean에 의존함. * ''SomePropsConfig'' 객체를 생성하면서 먼저 Field Injection을 시도하고 그 뒤에 ''@Bean''을 생성하는데, Field가 동일 설정 파일의 ''@Bean myProperties'' 객체에 의존하는 상황. ==== BeanFactoryPostProcessor ==== * [[http://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/beans/factory/config/BeanFactoryPostProcessor.html|BeanFactoryPostProcessor]] 구현체는 ''static''으로 등록해야 한다. 대표적으로 [[http://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/context/support/PropertySourcesPlaceholderConfigurer.html|PropertySourcesPlaceholderConfigurer]]가 그렇다. ==== Bean의 List/Map 주입받기 ==== * [[https://www.baeldung.com/spring-autowire-generics|Spring Autowiring of Generic Types | Baeldung]] private List dataSources; // 모든 DataSource Bean 목록 주입 private Map dataSourcesByBeanName; // beanName 을 key로 하여 모든 DataSource bean 주입