스프링의 빈을 등록하려면 자바 코드의 @Bean이나 XML의 <Bean> 등을 통해서 설정 정보에 직접 등록할 스프링 빈을 나열해야 한다. 그런데 만약 빈의 개수가 많아지면 일일이 하기 귀찮아진다.
그래서 스프링은 설정 정보가 없어도 빈을 등록할 수 있는 컴포넌트 스캔이라는 기능을 제공한다. 말 그대로 전체 파일을 스캔해서 빈을 등록하는 것으로, 스캔 범위를 제한하거나 스캔에서 제외하고 싶은 대상을 특정할 수도 있다.
이전의 AppConfig가 아닌 컴포넌트 스캔을 이용한 AutoAppConfig 클래스를 작성해보자.
@Configuration
@ComponentScan(
excludeFilters = @Filter(type = FilterType.ANNOTATION, classes = Configuration.class
))
public class AutoAppConfig { }
@ComponentScan 옵션에 excludeFilters가 있는데 이것은 기존의 @Configuration이 붙은 설정 정보를 스캔 대상에서 제외하고 실행하기 위해 쓰인 옵션이다.
컴포넌트 스캔은 말 그대로 @Component가 붙은 클래스를 스캔해서 스프링 빈으로 등록하기 때문에 @Component를 붙여서 간단하게 빈으로 설정해 줄 수 있다.
특정 클래스를 빈으로 설정할 때 의존관계 주입이 필요한 경우가 있을 수도 있는데 그때는 생성자에 @Autowired를 붙이면 스프링이 자동으로 의존관계를 주입해준다.
@Component
public class MemberServiceImpl implements MemberService {
private final MemberRepository memberRepository;
@Autowired
public MemberServiceImpl(MemberRepository memberRepository) {
this.memberRepository = memberRepository;
}
...
}
@ComponentScan은 빈을 등록할 때 이름 전략이 있는데, 기본적으로 원래 클래스명을 사용하되 맨 앞글자만 소문자로 바꿔서 사용한다. (MemberServiceImpl -> memberServiceImpl) 아니면 이름을 직접 지정해줄 수 있다. (하지만 직접 지정할 일은 별로 없을 듯)
앞서 말했듯이 컴포넌트 스캔의 범위를 제한하거나 대상을 지정할 수 있는데 @ComponentScan 어노테이션의 옵션으로 이를 설정할 수 있다.
- basePackages = {"hello.core", "hello.service"} // 루트 패키지 지정
- basePackageClasses // 지정한 클래스의 패키지를 루트 패키지로 지정
- default : @ComponentScan이 붙은 설정 클래스의 패키지가 루트 패키지로 지정됨
- 권장하는 방법 : 프로젝트의 시작 루트에 메인 설정 정보(AppConfig 등..)를 배치
- 스프링 부트는 프로젝트의 시작 루트에 @SpringBootApplication을 두는데, 이 어노테이션 안에 @ComponentScan이 포함되어 있다.
- includeFilters : 컴포넌트 스캔 대상을 추가로 지정한다
- includeFilters = @Filter(type = FilterType.ANNOTATION, classes = ...)
- excludeFilters : 컴포넌트 스캔에서 제외할 대상을 지정한다
- FilterType
- ANNOTATION : 기본값, 어노테이션 인식
- ASSIGNABLE_TYPE : 지정한 타입과 자식 타입을 인식
- ASPECTJ : AspectJ 패턴 사용
- REGEX : 정규 표현식
- CUSTOM : TypeFilter 인터페이스 구현해서 사용
- FilterType
참고로 includeFilters를 쓸 일은 거의 없다고 한다.
컴포넌트 스캔의 기본 대상은 다음과 같다.
- @Component
- @Controller (스프링 MVC 컨트롤러로 인식)
- @Service (개발자들이 그냥 보기 좋음)
- @Repository (스프링 데이터 접근 계층으로 인식. 데이터 계층의 예외를 추상화해준다)
- @Configuration (스프링 설정 정보로 인식. 스프링 빈에 싱글톤 패턴 적용)
사실 @Component 말고 다른 어노테이션 안에는 모두 @Component가 있다. 그리고 어노테이션이 상속되는 건 자바의 기능이 아니고 스프링이 지원하는 기능이다.
이제 우리는 스프링의 컴포넌트 스캔을 통해서 자동으로 스프링 빈을 등록할 수 있게 되었다. 즉 스프링 빈을 자동 또는 수동으로 등록할 수 있다는 것인데, 만약에 빈을 중복으로 등록하면 어떻게 될까?
스프링에서는 수동으로 등록한 빈이 자동으로 등록한 빈보다 우선순위가 높기 때문에 중복되었을 경우 자동으로 등록된 빈이 오버라이딩 된다. 흠.. 근데 우리는 혼자 일하지 않는다. 누구는 자동 등록을 하고 누구는 수동 등록을 하면 아마 X판이 되지 않을까?.. 끔찍한 버그가 탄생할 수도 있다.
그래서 최근 스프링 부트에서는 빈이 중복되면 아예 오류를 발생시키도록 기본 값을 바꾸었다고 한다. 물론 오버라이딩 되도록 설정할 수 있지만 기본값은 오류를 내뱉게 되어있다.
Consider renaming one of the beans or enabling overriding by setting
spring.main.allow-bean-definition-overriding=true
'Spring' 카테고리의 다른 글
nginx - 리버스 프록시로 스프링 CORS 문제 해결하기 (0) | 2022.04.07 |
---|---|
생성자 주입과 스프링 (0) | 2022.04.06 |
싱글톤의 단점과 스프링의 싱글톤 컨테이너 (0) | 2022.04.03 |
POJO에서 스프링으로의 전환 (0) | 2022.03.26 |
IoC (0) | 2022.03.25 |