이제까지
1. 관심사의 분리를 위한 자바 코드를 이용한 설정 파일 + 의존관계 주입
https://bbeomgeun.tistory.com/141
2. 스프링 컨테이너 + 자바 설정 파일을 이용한 의존관계 주입으로 싱글톤 컨테이너 구성
https://bbeomgeun.tistory.com/142
스프링에서 AppConfig.class 설정 파일과 ApplicationContext 스프링 컨테이너를 이용해서 직접 @Configuration과 @Bean을 붙여서 컨테이너에 스프링 빈을 등록했다.
하지만 이렇게 수동으로 등록을 하면, 매번 빈을 등록할 때마다 AppConfig.class에 등록을 해줘야 하고, @bean을 붙여줘야 한다. 또는 XML 설정 파일을 사용하면 <bean>으로 넣어줘야 했다.
프로젝트가 커지면 반복되는 과정이며, 누락될 수도 있다는 문제점이 있다.
따라서 이번엔 스프링에서 제공하는 @Component 어노테이션과 컴포넌트 스캔을 이용해서 설정 정보 없이도 자동으로 스프링 컨테이너에 빈을 등록하는 것을 정리해보려 한다.
추가로 @AutoWired 어노테이션을 통해 의존관계를 자동으로 주입할 수도 있다.
1. 컴포넌트 스캔
- 컴포넌트 스캔이란 말 그대로 @Component 어노테이션이 붙어 있는 클래스를 스캔해서 스프링 빈으로 등록한다.
- 이전에는 AppConfig.class 설정 파일에서 @Bean으로 직접 등록하고, 의존 관계 또한 정의했었다.
- 컴포넌트 스캔을 사용하게 되면, 클래스에 @Component를 붙이고, 의존 관계 또한 클래스 안에서 직접 정의하면 된다.
2. 사용법
- 설정 파일에서 @ComponentScan 어노테이션을 붙이면 자동으로 컴포넌트들을 스캔해서 스프링 컨테이너를 구성한다
- 테스트로는 기존에 하던 것처럼 AppConfig.class에 @Bean 정보들을 모두 지우고, @ComponentScan만 붙이면 된다.
- 설정 파일에 빈 등록 및 의존관계 정보가 없어도 컴포넌트 스캔을 이용해서 컨테이너가 자동으로 구성되는 것을 확인할 수 있다.
- 복잡하지만 부트를 이용한다면 스프링 부트의 시작 설정 파일인 @SpringBootApplication파일에 컴포넌트 스캔이 포함되어 있다.
(결국 내가 신경 쓸건 빈으로 등록할 클래스에 @Component 붙이는 것과 @Autowired로 의존관계만 설정해주면 된다)
3. 컴포넌트 스캔 과정
- @Component가 붙은 클래스들을 컨테이너에 모두 등록한다.
- @AutoWired를 이용해서 의존 관계를 주입한다. 위의 예시는 생성자 주입인데, 다음에 의존 관계 주입 방법 4가지를 알아볼 예정이다.
4. 컴포넌트 스캔의 범위
@ComponentScan(
basePackages = "packages.xxx"
)
를 이용해서 탐색할 패키지의 시작 위치를 설정할 수 있다.
위의 경우, packages.xxx를 포함한 하위 패키지 모두 스캔이 된다.
만약 지정하지 않으면 @ComponentScan이 붙은 설정 정보 클래스가 탐색 시작 위치가 된다.
+ 추천하는 방법
- 패키지 위치를 지정하기보다, 프로젝트의 최상단에 설정 정보 파일을 둔다면 자동으로 모든 하위 패키지가 스캔된다.
- 스프링 부트를 이용하면 스프링 부트의 대표 시작 정보인 @SpringBootApplication를 프로젝트의 시작 루트 위치에 두게 된다. 그리고 이 @SpringBootApplication 안에 @ComponentScan이 들어있다.
5. 컴포넌트 스캔의 대상
- 기본적으로 @Component를 스캔한다.
하지만 스프링 MVC에서 사용하는 @Controller, @Service, @Repository도 스캔 대상이고 @Configuration 또한 스캔 대상이다. (모두 안에 @Component가 포함되어 있다.)
+ 수동 빈과 자동 빈이 중복될 경우?
만약 AppConfig.class 설정 파일에
@Bean(name = "tempBean")을 수동 등록해주고
@Configuration
@ComponentScan
public class AppConfig{
@Bean(name = "tempBean")
public TempBean tempBean(){
return new TempBean();
}
}
@Component
public class TempBean 클래스를 컴포넌트 어노테이션으로 자동 등록해주면 어떻게 될까?
@Component
public class TempBean{}
-> 일단 tempBean이라는 빈끼리 이름이 겹치게 된다.
- 결과적으로 수동 등록한 것이 우선권을 가지며, 수동 빈이 자동 빈을 오버라이딩해버린다.
<수동 빈 등록 시 남는 로그>
Overriding bean definition for bean 'tempBean' with a different
definition: replacing
위의 상황은 오류가 난다면 보통 의도한 경우가 아닌, 놓치고 간 까다로운 경우이므로 스프링 부트에서는 수동, 자동 빈 등록이 충돌되면 오류가 나도록 바뀌었다.
Consider renaming one of the beans or enabling overriding by setting
spring.main.allow-bean-definition-overriding=true
위의 오류가 난다.
'개발 공부 > 스프링' 카테고리의 다른 글
[SpringBoot] Error - Failed to configure a DataSource: 'url' attribute is not specified and no embedded datasource could be configured. (0) | 2022.02.04 |
---|---|
스프링 - 의존 관계 주입 방법 4가지 (0) | 2021.09.17 |
스프링 - 스프링 컨테이너, 싱글톤 (0) | 2021.09.17 |
스프링 - 의존 관계와 DI, Ioc 컨테이너 (0) | 2021.09.16 |
스프링 MVC - 서블릿을 통한 HTTP 요청(GET, POST, API, JSON) (0) | 2021.09.08 |