- 자동 주입과 함께 사용되는 기능
- 스프링이 직접 클래스를 검색해서 빈으로 등록해주는 기능
- 설정 코드가 크게 줄어듦
Component-scan은 xml에 일일이 빈등록을 하지않고 각 빈 클래스에 @Component를 통해 자동 빈 등록이 된다.
@Component @Controller @Service @Repository와 같은 어노테이션을 자동 등록 처리해준다.
@Component 애노테이션으로 스캔 대상 지정
스프링이 검색해서 빈으로 등록할 수 있으려면 클래스에 @Component 애노테이션을 붙여야 한다.
이 애노테이션은 해당 클래스를 스캔 대상으로 표시한다.
- @Component 애노테이션에 값을 주면 그 값을 빈 이름으로 사용한다.
ex. @Component("listPrinter")
@ComponentScan 애노테이션으로 스캔 설정
@Component 애노테이션을 붙인 클래스를 스캔해서 스프링 빈으로 등록하려면, 설정 클래스에 @ComponentScan 애노테이션을 적용해야한다.
@Configuration
@ComponentScan(basePackages = {"spring"})
public class AppCtx{
...
}
이 코드를 보면 AppCtx 클래스에서
@ComponentScan 애노테이션을 사용하여 @Component 애노테이션이 붙은 클래스를 검색해서 빈으로 등록해주기 때문에 설정 코드가 확연히 줄어든다.
또 컴포넌트 스캔 애노테이션을 살펴보면 basePackages 속성값은 {"spring"}이다. 이 속성은 스캔 대상 패키지 목록을 지정하는 것이다.
이는 spring 패키지와 그 하위 패키지에 속한 클래스를 스캔 대상으로 설정한다. 스캔 대상에 해당하는 클래스중 @Component 애노테이션이 붙은 클래스의 객체를 생성해 빈으로 등록한다.
스캔 대상에서 제외하거나 포함하기
excludeFilters 속성을 사용하면 스캔할 때 특정 대상을 자동 등록 대상에서 제외할 수 있다.
// 정규 표현식을 사용해서 제외 대상을 지정한다.
// "spring."으로 시작하고 Dao로 끝나는 정규 표현식을 지정
@ComponentScan(basePackages = {"spring"},
excludeFilters = @Filter(type = FilterType.REGEX, pattern = "spring\\..*Dao"))
// AspectJ 패턴을 사용해 대상을 지정한다.
// spring 패키지의 Dao로 끝나는 타입을 지정
// AspectJ 패턴이 동작하려면 의존 대상에 aspectjweaver모듈을 추가해야한다.
@ComponentScan(basePackages = {"spring"},
excludeFilters = @Filter(type = FilterType.ASPECTJ, pattern = "spring.*Dao"))
// 특정 애노테이션을 붙인 타입을 컴포넌트 대상에서 제외한다.
// 패턴은 Stringp[] 타입이므로 배열을 이용해 패턴을 한 개 이상 지정할 수 있다.
@ComponentScan(basePackages = {"spring", "spring2"},
excludeFilters = @Filter(type = FilterType.Annotation, pattern = {NoProduct.class, ManualBean.class}))
// 특정 타입이나 그 하위 타입을 컴포넌트 스캔 대상에서 제외한다.
@ComponentScan(basePackages = {"spring"},
excludeFilters = @Filter(type = FilterType.ASSIGNABLE_TYPE, classes = MemberDao.class))
// 설정할 필터가 2개 이상이면 excludeFilters 속성에 배열을 사용해서 목록을 전달하면 된다.
@ComponentScan(basePackages = {"spring"},
excludeFilters = {
@Filter(type = FilterType.ANNOTATION, classes = ManualBean.class),
@Filter(type = FilterType.REGEX, pattern = "spring2\\..*")
}
@Component 애노테이션을 붙인 클래스만 스캔 대상에 포함되는 것이 아니다.
- @Component
- @Controller
- @Service
- @Repository
- @Aspect
- @Configuration
@Aspect를 제외하고 나머지 애노테이션은 @Component 애노테이션에 대한 특수 애노테이션이다.
컴포넌트 스캔에 따른 충돌 처리
컴포넌트 스캔 기능을 사용해서 Bean을 등록할 경우, 아래와 같은 두 가지 충돌이 발생 가능
- Bean 이름의 충돌
- 수동 등록에 따른 충돌
2-1. Bean 이름 충돌
- 서로 다른 패키지에 같은 클래스의 이름이 존재하고, 두 클래스 모두 @Component 어노테이션이 붙게 된다면,
Exception이 발생하게 됨 - 이럴 경우, 둘 중 하나에 명시적으로 Bean 이름을 지정해서 이름 충돌을 피해야 함
2-2. 수동 등록에 따른 충돌
- 같은 클래스를 같은 이름으로 설정할 때:
- @Component 어노테이션을 통해 이미 지정한 Bean의 클래스 이름이 존재하지만,
클래스 설정에 직접 해당 클래스를 동일한 이름으로 정해 등록하는 경우 발생 - 즉, 스캔할 때 사용하는 Bean 이름과 수동 등록한 이름이 같을 경우, 수동 등록한 Bean이 우선시 됨
- @Component 어노테이션을 통해 이미 지정한 Bean의 클래스 이름이 존재하지만,
- 같은 클래스를 다른 이름으로 설정할 때:
- 만약, 스캔할 때 사용하는 Bean 이름과 동일한 클래스를 다른 이름으로 수동 등록하는 경우에는
다른 이름의 두 개의 Bean이 만들어지게 됨 - 이런 경우에는 @Qualifier 어노테이션을 통해 알맞은 Bean을 선택해야 함
- 만약, 스캔할 때 사용하는 Bean 이름과 동일한 클래스를 다른 이름으로 수동 등록하는 경우에는
Reference.
'초보 웹 개발자를 위한 스프링5 프로그래밍 입문' link1
'🔥 > Spring' 카테고리의 다른 글
[spring] 빈 라이프 사이클과 범위 (0) | 2021.08.31 |
---|---|
[Spring] "회초리단" 스프링 스터디 1차 (0) | 2021.08.20 |
[Spring] DI의 세가지 방법 (0) | 2021.08.18 |
[Spring] 의존성 주입(DI)이란 ? (0) | 2021.08.18 |