@(Annotation)을 이용한 Spring Container Configuration
이 글은 아래의 공식 문서를 참조해서 작성했습니다
https://docs.spring.io/spring-framework/docs/current/reference/html/core.html#beans-java
Core Technologies
In the preceding scenario, using @Autowired works well and provides the desired modularity, but determining exactly where the autowired bean definitions are declared is still somewhat ambiguous. For example, as a developer looking at ServiceConfig, how do
docs.spring.io
Spring은 의존성 설정을 위해 xml 파일 또는 @(어노테이션)을 사용한다
이제는 xml 파일 기반의 configuration을 많이 사용하지 않기 때문에 어노테이션 기반 컨테이너 설정을 할 때가 많다
스터디를 하다가 @Bean과 @Component 어노테이션의 차이에 대한 주제가 나와서 정리해보면 좋겠다고 생각했다
Spring IoC 컨테이너는 @Configuration이 적용된 클래스, @Bean이 적용된 메서드에 대해 환경 설정을 적용한다.
@Bean
Spring IoC 컨테이너에 의해 관리될 객체를 인스턴스화 하고, 구성하고, 초기화 하는 데 사용되는 메서드를 표시한다
@Bean 어노테이션을 메서드에 적용하면 해당 메서드 반환 값 유형의 빈을 ApplicationContext에 등록한다
기본적으로 빈 이름은 메서드 이름과 같다
@Configuration
public class AppConfig {
@Bean
public TransferService transferService(AccountRepository accountRepository) {
return new TransferServiceImpl(accountRepository);
}
/*
인터페이스 반환도 가능하지만 예상과 다른 결과가 나타날 수 있다
@Bean
public TransferService transferService() {
return new TransferServiceImpl();
}
*/
}
이렇게 선언된 transferService라는 이름의 Bean을 TransferServiceImpl 형식의 인스턴스에 바인딩해서 사용할 수 있다
해당 빈을 정의하는 데 필요한 종속성에 대한 매개 변수를 가질 수 있으며, 이는 Constructor DI 방식과 유사하다
기존 xml 기반 설정의 과 동일한 역할을 수행하고, @Bean 어노테이션은 @Component와 함께 사용할 수도 있지만 @Configuration 빈과 함께 사용하는 게 일반적이다
@Configuration
@Configuration 어노테이션을 클래스에 적용하면 클래스 수준 객체를 빈으로 등록한다
클래스 내부의 @Bean 어노테이션이 적용된 메서드들 간에 서로 호출하면서 빈들 간의 종속성을 정의할 수 있다
@Configuration
public class AppConfig {
@Bean
public BeanOne beanOne() {
return new BeanOne(beanTwo());
}
@Bean
public BeanTwo beanTwo() {
return new BeanTwo();
}
}
@Configuration 클래스 내에서 @Bean을 사용했을 때에만 같은 클래스 안의 종속성을 주입받을 수 있다
예시에서 AppConfig 클래스가 @Configuration 어노테이션이 아닌 @Component를 사용한다면 beanOne 메서드는 beanTwo 메서드 종속성을 주입받을 수 없을 것이다
@Bean은 @Configuration 어노테이션과 세트로만 활용할 수 있을까?
아니다
@Bean 어노테이션은 @Configuration이 적용되지 않은 클래스의 메서드에서도 사용할 수 있고, 이 사용 방식을 "lite" 모드라고 한다
@Component 어노테이션 내부 혹은 일반 클래스에 선언된 메서드는 "lite" 모드로 간주된다(기존 클래스의 주 목적과 달라질 수 있다)
@Configuration이 적용된 클래스에서의 활용 방식과 다르게, lite 모드에서의 @Bean 메서드들은 서로 간의 종속성을 정의할 수 없다
일반적으로는 @Bean 메서드가 @Configuration 클래스 내에 선언되어 "full" 모드가 항상 사용되고 @Bean들 간의 상호 메서드 참조가 컨테이너 라이프사이클에 의해 관리되게 한다
이것은 동일한 @Bean 메서드가 실수로 호출되는 것을 방지해서 lite 모드에서 추적이 어렵다는 버그를 방지할 수 있다
@Configuration 어노테이션이 적용되면 클래스 자체, 그리고 @Bean 메서드들이 모두 빈으로 등록된다