스프링에서 빈을 등록하는 법은 여러가지가 존재한다.
@Controller, @Service, @Repository 등으로 빈으로 등록하는 법이 있고 configuration 관련 객체는 @Bean, @Componet으로 스프링 컨테이너에 빈으로 등록할 수 있다. 물론 @Controller, @Service와 같은 어노테이션도 올라가보면 @Component 어노테이션이 붙어있다.
Bean의 경우 개발자가 컨트롤이 불가능한 외부 라이브러리를 Bean으로 등록하고싶은 경우에 사용된다. 빈은 @Configuration과 세트로 사용되는데 config 파일들을 java 클래스의 형태로 작성할 수 있도록 도와주는 어노테이션이다.
예를 들어 DataSource나 Spring security의 PasswordEncoder와 같은 외부 라이브러리는 따로 수정하는 것이 힘들기 때문에 @Bean 어노테이션을 이용하여 컨테이너에 등록한다.
@Bean은 메소드 레벨에서 선언되며, 반환되는 객체를 개발자가 수동으로 빈으로 등록하는 어노테이션이다. Bean을 모아 놓은 Config파일에 붙은 @Configuration 어노테이션에는 결국 Componet 어노테이션이 붙어있다.
@Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Bean {
...
}
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface Configuration {
...
}
@Bean
public PasswordEncoder passwordEncoder(){
return new BCryptPasswordEncoder();
}
Component는 Bean과 반대로 개발자가 임의로 생성한 클래스를 빈으로 등록싶은 경우에 사용된다. 개발자가 직접 컨트롤이 가능한 경우 Component로 등록한다.
@Component는 클래스 레벨에서 선언함으로써 스프링 런타임시에 컴포넌트 스캔을 하여 자동으로 빈을 찾고 등록하는 어노테이션이다.
만약 Component위치 Bean을 사용하면 컴파일 과정에서 에러가 발생한다.(반대로 해도 동일하다)
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Indexed
public @interface Component {
...
}
@Component
public class Test{
...
}
@Bean과 @Componet의 가장 큰 차이점은 내가 생각하기에는 개발자가 컨트롤할 수 있는지에 대한 유무이다.
@Bean은 외부라이브러리를 빈으로 등록하고 싶을때 사용하면 되는 것이고 @Component는 개발자가 만들거나 가져온 클래스를 빈으로 등록하고 싶을 때 사용하면 된다.
참조
https://jojoldu.tistory.com/27
https://seeminglyjs.tistory.com/414