@Component, @Bean, @Autowired
자주 사용하면서도 정확하게 무슨 용도로 사용되는지, 어떤 동작 원리를 가지는지, 어떤 차이가 있는지 잘 몰랐던 부분에 대해서 공부합니다.
먼저 Annotation에 대해서 간단하게 알아보겠습니다.
Annotation은 Java 5부터 추가된 문법 요소로, 코드 사이에 주석처럼 쓰이며 특별한 의미, 기능을 수행하도록 하는 기술입니다.
실제 데이터가 아닌 데이터를 위한 데이터로 메타데이터 (meta data)로 불립니다.
어노테이션의 용도
- 컴파일러에게 코드 작성 문법 에러를 체크하도록 정보 제공
- 소프트웨어 개발 툴이 빌드나 배치 시 코드를 자동으로 생성할 수 있도록 정보 제공
- 실행 시 (런타임) 특정 기능을 실행하도록 정보 제공
어노테이션을 사용하기 위한 순서
- 어노테이션 정의
- 클래스에 어노테이션 배치
- 코드가 실행되는 중 Reflection을 이용하여 추가 정보를 획득하여 기능 실행
* Reflection
Java의 Reflection은 JVM에서 실행되는 애플리케이션의 런타임 동작을 검사하거나 수정할 수 있는 기능이 필요한 프로그램에서 사용됩니다. 쉽게 클래스의 구조를 개발자가 확인할 수 있고, 값을 가져오거나 메서드를 호출하는 데 사용됩니다.
이 기술은 스프링 프레임워크에 사용되며 Reflection을 사용하여 스프링에서 런타임시 개발자가 등록한 빈을 애플리케이션에서 가져와서 사용할 수 있게 됩니다.
(Annotation, Reflection 둘 다 조금 더 자세하게 공부해봐도 좋은 부분인 것 같아 따로 다시 공부할 예정입니다.)
@ComponentScan 란,
@Component, @Service, @Repository, @Controller, @Configuration 어노테이션이 붙은 클래스 Bean 들을 찾아서 Context에 bean 등록을 해주는 어노테이션입니다.
bean 등록을 하는 방법에는 @어노테이션을 이용하는 방법과,
ApplicationContext.xml 파일에 <bean id = "example" class = "example" /> 처럼 직접 등록하는 방법이 있습니다.
@SpringBootApplication
@ComponentScan 어노테이션을 통해 bean 등록을 한다고 하는데, 저의 경우는 @ComponentScan 어노테이션을 직접적으로 사용한 적이 한 번도 없습니다. 이유는 @SpringBootApplication 어노테이션에 있습니다.
@ComponentScan는 component scan의 시작 지점을 설정하는 basePackages(), basePackageClasses() 두 가지 속성이 있습니다.
basePackages()는 scan을 시작할 패키지를 문자열로 지정하고, basePackageClasses()는 스캔을 시작할 클래스 타입을 지정합니다.
결론적으로 @SpringBootApplication 내부에서 ComponentScan이 기본 패키지에 대해서 설정되어 있기 때문에 직접적으로 어노테이션을 사용하지 않아도 작동하는 것입니다.
@Component 란,
@Component는 개발자가 직접 작성한 Class를 Bean으로 등록하기 위한 Annotation 입니다.
* 위에서 설명한 스프링의 컴포넌트 스캔 (@ComponentScan) 기능에 의해 스캔될 때, 주어진 패키지 내에서 @Component 어노테이션이 적용된 클래스를 식별하고, 그러한 클래스의 빈을 생성하여 ApplicationContext에 등록합니다.
* (value = "") 옵션이 있고, 해당 옵션을 사용하지 않는다면 class의 이름을 camelCase로 변경한 것을 bean id로 사용합니다.
그렇다면 @Controller, @Service, @Repository 어노테이션은 무엇일까요?
@Controller, @Service, @Repository
@Controller, @Service, @Repository 어노테이션들은 @Component 어노테이션의 구체화된 형태입니다.
어노테이션을 세분화 함으로써 가독성 측면에서 해당 각각의 어노테이션을 가진 클래스의 역할을 알 수 있게 됩니다.
더 자세한 내용은 아래 사이트를 참고하시면 좋을 것 같습니다.
https://springbootdev.com/2017/07/31/spring-framework-component-service-repository-and-controller/
@Bean 이란,
@Bean 어노테이션은 개발자가 직접 제어가 불가능한 외부 라이브러리 등을 Bean으로 만들려고 할 때 사용됩니다.
* (name = "") 옵션이 있고, 해당 옵션을 사용하지 않는다면 method 이름을 camelCase로 변경한 것이 bean id로 등록됩니다.
// 암호화에 필요한 PasswordEncoder Bean 등록
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
// authenticationManager Bean 등록
@Bean
@Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
@Bean과 같이 알아야 할 @Configuration
@Configuration 어노테이션은 해당 클래스에서 1개 이상의 Bean을 생성하고 있음을 명시합니다.
그러므로 @Bean 어노테이션을 사용하는 클래스는 반드시 @Configuration과 함께 사용되어야 합니다,
@Autowired, @Qualifier
@Autowired는 field(속성) , setter, method, constructor(생성자)에서 사용하며 Type에 따라 자동으로 bean을 주입합니다.
Type을 먼저 확인하여 못 찾는 경우에는 name에 따라서 bean을 주입합니다.
이때 해당 타입의 bean 객체가 존재하지 않거나, 2개 이상 존재할 경우 스프링은 예외가 발생합니다.
같은 타입의 bean이 두 개 이상 존재하는 경우, 어떤 bean을 주입해야 할지 알 수 없기 때문에 스프링 컨테이너를 초기화하는 과정에서 예외가 발생하는데요. 이 경우 @Qualifier 어노테이션을 @Autowired와 함께 사용하여 어떤 bean을 사용할지 명시할 수 있습니다.
* 추가적으로 @Autowired를 사용할 경우 순환 참조가 발생할 수 있기 때문에 @Autowired 보다 생성자 주입 방식이 더 권장되고 있습니다.
'Programming > Spring' 카테고리의 다른 글
[ELK+R스택 구축하기] docker로 ELK 구성하여 Spring Boot 로그 쌓기 (1) (5) | 2023.05.05 |
---|---|
[Spring Boot] 스프링과 스프링 부트 (0) | 2022.06.09 |
[Spring] Component Scan과 Function을 사용한 빈 등록 방법 (0) | 2022.05.29 |
[Spring] @Autowired 동작 원리 - BeanPostProcessor (0) | 2022.05.29 |
[Spring] @Autowired의 다양한 사용 방법 - required, Primary, Qualifier (0) | 2022.05.29 |