@Configuration + @Bean
@Configuration + @Bean 어노테이션을 사용하는 이유는 아래와 같다.
- 라이브러리, 내부 클래스 등 개발자가 직접 제어 불가능한 클래스를 Bean 등록할때 사용한다.
- 다형성을 활용하여 여러 구현체를 Bean 등록 해야할때 사용한다.
@Configuration 어노테이션이 존재 하는곳에 @Bean 어노테이션을 사용해 여러개의 구현체를
Spring Bean 으로 등록할 수 있다.
@Bean 어노테이션은 반드시 @Configuration 어노테이션과 함께 사용해야 한다고 하는데
이유는 아래와 같다.
@Configuration 과 @Bean 어노테이션을 함께 사용해야 하는 이유
@Configuration 과 @Bean 어노테이션을 함께 쓰라고 강조하는 이유는
@Configuration 어노테이션에 적용되는 프록시 패턴 부가 기능이 적용되기 떄문이다.
@Configuration 어노테이션은 안에 @Component 어노테이션이 존재하기 때문에
@ComponentScan 어노테이션에 의해 Spring 빈으로 등록 되어진다.
그럼에도 불구하고 스프링이 @Configuration 을 따로 만든 이유는 CGLib으로
프록시 패턴을 적용해 @Bean 어노테이션을 통해 수동으로 등록하는 스프링 빈이
반드시 싱글톤으로 생성됨을 보장하기 위해서이다.
아래와 같은 스프링 Bean 등록을 위한 클래스가 존재한다고 예를 들어본다.
@Component
public class OboTestClass{
}
@Component 어노테이션을 사용하여 위 클래스를 스프링 Bean 으로 등록을 한다면
Spring IOC 를 통해 스프링이 위 클래스의 객체 생성을 제어 및 컨트롤하게 된다.
하지만 여러개의 수동 빈을 등록하기 위해서 @Configuration, @Bean 을 사용한다고 하자
@Configuration
public class OboTestConfiguration{
@Bean
public OboFirstBean oboFirstBean(){
return new oboFirstBean();
}
@Bean
public OboSecondBean oboSecondBean(){
return new oboSecondBean(oboFirstBean());
}
@Bean
public OboThirdBean oboThirdBean(){
return new oboThirdBean(oboFirstBean());
}
}
위와 같이 oboSecondBean, oboThirdBean 메서드를 호출하게 되면 불필요하게
여러개의 oboFirstBean 빈이 생성이 된다. 스프링은 이러한 문제를 방지하고자 @Configuration이 있는
클래스를 생성할 때 CGLib 를 사용해 프록시 패턴을 적용한다.
@Bean 이 있는 메소드를 호출하여도 항상 동일한 객체를 반환하여 싱글톤을 보장하도록 한다.
@Configuration
public class OboTestConfigurationProxy extends OboTestConfiguration{
private Object object;
@Bean
public OboFirstBean oboFirstBean(){
if(OboFirstBean == null){
object = super.oboFirstBean();
}
return object;
}
@Bean
public OboSecondBean oboSecondBean(){
return super.oboSecondBean();
}
@Bean
public OboThirdBean oboThirdBean(){
return super.oboThirdBean();
}
}
위 코드와 같이 생성되어 있는지 판단하여 Bean 생성을 결정하고 super 키워드를 통해
메서드 호출을 진행한다.
@Component
개발자가 직접 작성한 클래스에 대해서 Bean 등록을 할때 사용하는 어노테이션이다.