// 다른 클래스에서 Bean으로 불러 사용이 가능함
@Component
public class MyComponent{
// do something
}
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdater{
// config ...
@Bean
public PasswordEncoder passwordEncoder(){
return new BCryptPasswordEncoder();
}
}
위 내용으로 이해가 바로 가지 않아 아래 예제를 통하여 이해를 하였습니다.
// @Configuration 사용 예제
@Configuration
public static class Config{
@Bean
public SimpleBean simpleBean(){
return new SimpleBean();
}
@Bean
public SimpleBeanConsumer simpleBeanConsumer(){
return new SimpleBeanConsumer(simpleBean());
}
}
// @Component 사용 예제
@Component
public static class Config{
@Bean
public SimpleBean simpleBean(){
return new SimpleBean();
}
@Bean
public SimpleBeanConsumer simpleBeanConsumer(){
return new SimpleBeanConsumer(simpleBean());
}
}
@Configuration 애노테이션과 @Component 애노테이션은 동작하는 방식이 비슷해 보인다. 둘다 애노테이션이 기술된 클래스를 빈으로 등록시키며 내부의 @Bean 애노테이션이 붙은 클래스들을 스프링컨텍스트에 등록시킨다
위의 예제 소스에서는 서로 결과가 다르다. 각 예제마다 simpleBeanConsumer() 메소드 내에서 simpleBean()를 호출하는 부분이 있는데 이 부분이 동작하는 방식이 다른 것이다. 첫 번째 예제의 메소드에서는 simpleBean()를 호출시 스프링 컨텍스트에 등록되어 있는 SimpleBean 클래스를 반환하지만 두번째 예제에서는 순수 메소드 호출을 한것 처럼 스프링 컨텍스트에 등록되어 있는 빈이 반환되는 것이 아니라 새로 생성된 빈이 반환된다. 이 부분을 주의해서 작성해야 한다.
두 번째 예제를 첫 번째 예제코드처럼 작동하도록 하기 위해서는 다음과 같이 작성한다.
@Component
public static class Config{
@Autowired
SimpleBean simpleBean;
@Bean
public SimpleBean simpleBean(){
return new SimpleBean();
}
@Bean
public SimpleBeanConsumer simpleBeanConsumer(){
return new SimpleBeanConsumer(simpleBean);
}
}
이 차이는 CGLIB(Code generation library)이 두 애노테이션 마다 다르게 동작하기 때문인데 기본적으로 @Bean 메소드들은 최초 한번 호출되어서 생성된 객체가 스프링 컨텍스트에 저장이 되며 @Configuration 애노테이션이 사용된 클래스 내부에서는 @Bean 메소드의 내부에서 호출한 메소드가 @Bean 메소드일 경우 컨텍스트에 등록된 빈을 반환하도록 되어 있다고 한다.