728x90
- 스프링이 직접 클래스를 검색해서 빈으로 등록해주는 기능으로 클래스에 @Component 애노테이션을 붙여야 함
- 설정 클래스에 빈으로 등록하지 않아도 원하는 클래스를 빈으로 등록할 수 있으므로 컴포넌트 스캔 기능을 사용하면 설정 코드가 크게 줄어든다
- @Component 애노테이션에 값을 주었는지에 따라 빈으로 등록할 때 사용할 이름이 결정됨
- 값을 주지 않으면 클래스 이름의 첫 글자를 소문자로 바꾼 이름을 빈 이름으로 사용함
- @Component 애노테이션을 붙인 클래스를 스캔해서 스프링 빈으로 등록하려면 설정 클래스에 @ComponentScan 애노테이션을 적용해야 함
...
@Configuration
@ComponentScan(basePackages={"spring"})
public class AppCtx {
@Bean
@Qualifier("printer")
public MemberPrinter memberPrinter1(){
....
- 스프링 컨테이너가 @Component 애노테이션을 붙인 클래스를 검색해서 빈으로 등록해주기 때문에 설정 코드가 줄어듦
스캔 대상에서 제외하거나 포함하기
- excludeFilters 속성을 사용하면 스캔할 때 특정 대상을 자동 등록 대상에서 제외할 수 있음
@ComponentScan(basePackages={"spring"},
excludeFilters = @Filter(type = FilterType.REGEX, pattern = "spring\\\\..*Dao"))
- Filter 애노테이션의 type 속성값으로 FilterType.REGEX를 주었는데 이는 정규표현식을 사용해서 제외 대상을 지정한다는 것을 의미
- pattern 속성은 FilterType에 적용할 값을 설정
- 위 설정은 spring.으로 시작하고 Dao로 끝나는 정규 표현식을 지정했으므로 spring.MemberDao 클래스를 컴포넌트 스캔 대상에서 제외함
@ComponentScan(basePackages={"spring"},
excludeFilters = @Filter(type = FilterType.ASPECTJ, pattern = "spring.*Dao"))
- FilterType.ASPECTJ를 필터로 설정할 수도 있으며 이는 AspectJ패턴을 사용해서 대상을 지정
- 이는 spring 패키지의 Dao로 끝나는 타입을 지정함
- 이 패턴이 동작하려면 aspectjweaver 모듈을 추가해야함
- patterns 속성은 String[] 타입이므로 배열을 이용해서 패턴을 한 개 이상 지정할 수도 있음
@ComponentScan(basePackages={"spring"},
excludeFilters = @Filter(type = FilterType.ANNOTATION,
classes = {NoProduct.class, ManualBean.class}))
- FilterType.ANNOTATION 으로 특정 애노테이션을 붙인 타입을 컴포넌트 대상에서 제외할 수도 있음
@ComponentScan(basePackages={"spring"},
excludeFilters = @Filter(type = FilterType.ASSIGNABLE_TYPE,
classes = MemberDao.class ))
- 특정 타입이나 그 하위 타입을 컴포넌트 스캔 대상에서 제외할 수도 있음
- classes 속성에는 제외할 타입 목록을 지정
@ComponentScan(basePackages={"spring"},
excludeFilters = {
@Filter(type = FilterType.ASSIGNABLE_TYPE, classes = MemberDao.class ),
@Filter(type = Filtertype.REGEX, pattern = "spring2\\\\..*")
}
- 설정할 필터가 두 개 이상이면 @ComponentScan의 excludeFilters 속성에 배열을 사용해서 @Filter 목록을 전달하면 됨
기본 스캔 대상
- @Component, @Controller , @Service, @Repository, @Aspect, @Configuration 애노테이션을 붙인 클래스가 컴포넌트 스캔 대상에 포함
- @Aspect 애노테이션을 제외한 나머지 애노테이션은 실제로는 @Component 애노테이션에 대한 특수 애노테이션
// @Controller 애노테이션은 실제로 아래와 같음 @Target({ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Documented @Component public @interface Controller { @AliasFor(annotation = Component.class) String value() default ""; }
컴포넌트 스캔에 따른 충돌 처리
- 컴포넌트 스캔 기능을 사용해서 자동으로 빈을 등록할 때에는 충돌에 주의해야 함
- 빈 이름 충돌과 수동 등록에 따른 충돌이 발생할 수 있음
빈 이름 충돌
- 다른 패키지에 같은 이름의 클래스가 존재하고 모두 @Component 애노테이션을 붙였다면 스프링 컨테이너 생성시 익셉션 발생
- 어떤 클래스를 빈으로 등록할 때 사용한 빈 이름이 타입이 일치하지 않는 다른 빈이름과 충돌 남
- 이런 문제는 컴포넌트 스캔 과정에서 쉽게 발생할 수 있고, 둘 중 하나에 명시적으로 빈 일므 지정
수동 등록한 빈과 충돌
- 같은 클래스에 @Component 애노테이션도 붙이고, 설정 클래스에도 같은 이름의 빈으로 등록 한다면?
- 스캔할 때 사용하는 빈 이름과 수동 등록한 빈 이름이 같은 경우 수동 등록한 빈이 우선
- 즉 같은 타입의 빈은 AppCtx에 정의한 한 개만 존재
- 다른 이름으로 같은 빈을 등록할 경우는 둘 다 등록 됨
'스프링' 카테고리의 다른 글
스프링5 프로그래밍 입문 - AOP 프로그래밍 (0) | 2023.10.28 |
---|---|
스프링5 프로그래밍 입문 - 빈 라이프사이클과 범위 (0) | 2023.10.02 |
스프링5 프로그래밍 입문 - 의존 자동 주입 (0) | 2023.10.02 |
스프링5 프로그래밍 입문 - 스프링 DI (0) | 2023.10.02 |
스프링5 프로그래밍 입문 - 스프링 프로젝트 시작하기 (0) | 2023.10.02 |