참고
Spring core basic 시리즈는 김영한 님의 "스프링 핵심 원리 - 기본편" 강의를 정리한 글입니다. 글에 첨부된 사진은 해당 강의의 강의 자료에서 캡쳐한 것입니다. 제 Github에만 올려뒀다가, 정보 공유와 강의 홍보(?)를 위해 블로그에도 업로드합니다. 마크다운을 잘 쓰지 못해서 가독성이 조금 떨어지는 점 양해 바랍니다.
스프링 핵심 원리 - 기본편 - 인프런 | 강의
스프링 입문자가 예제를 만들어가면서 스프링의 핵심 원리를 이해하고, 스프링 기본기를 확실히 다질 수 있습니다., - 강의 소개 | 인프런...
www.inflearn.com
컴포넌트 스캔 필터링
특정 대상을 컴포넌트 스캔 대상에 추가하거나, 제외할 수 있다.
includeFilters
: 컴포넌트 스캔 대상을 추가로 지정한다.excludeFilters
: 컴포넌트 스캔에서 제외할 대상을 지정한다.
임의의 annotation을 만들어서, 해당 annotation이 붙으면 컴포넌트 스캔 대상에 추가되거나 제외되게끔 해보자.
MyIncludeComponent.java
package com.kloong.corebasic1.scan.filter;
import java.lang.annotation.*;
@Target(ElementType.TYPE) //클래스 레벨에 붙는 annotation
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface MyIncludeComponent { }
MyExcludeComponent.java
package com.kloong.corebasic1.scan.filter;
import java.lang.annotation.*;
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface MyExcludeComponent { }
두 annotation에 붙은 3개의 annotation은 @Component
annotation에도 동일하게 존재한다.
Component.java
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Indexed
public @interface Component { /* 생략 */ }
이제 @MyIncludeComponent
가 붙으면 컴포넌트 스캔 대상에 추가되고, @MyExcludeComponent
가 붙으면 컴포넌트 스캔에서 제외되게끔 설정해보자.
BeanA.java
package com.kloong.corebasic1.scan.filter;
@MyIncludeComponent
public class BeanA {
}
@MyIncludeComponent
annotation을 붙였다.
BeanB.java
package com.kloong.corebasic1.scan.filter;
@MyExcludeComponent
public class BeanB {
}
@MyExcludeComponent
annotation을 붙였다.
ComponentFilterAppConfigTest.java
//package, import 생략
public class ComponentFilterAppConfigTest {
@Test
void filterScan() {
ApplicationContext ac =
new AnnotationConfigApplicationContext(ComponentFilterAppConfig.class);
BeanA beanA = ac.getBean("beanA", BeanA.class);
Assertions.assertThat(beanA).isNotNull();
assertThrows(NoSuchBeanDefinitionException.class,
() -> ac.getBean("beanB", BeanB.class));
}
@Configuration
@ComponentScan(
includeFilters =
@ComponentScan.Filter(type = FilterType.ANNOTATION,
classes = MyIncludeComponent.class),
excludeFilters =
@ComponentScan.Filter(type = FilterType.ANNOTATION,
classes = MyExcludeComponent.class)
)
static class ComponentFilterAppConfig {
}
}
includeFilters
에 MyIncludeComponent annotation을 추가해서 BeanA가 스프링 빈에 등록된다.- excludeFilters 에 MyExcludeComponent annotation을 추가해서 BeanB는 스프링 빈에 등록되지 않는다.
BeanB가 빈으로 등록되지 않았기 때문에, ac.getBean("beanB", BeanB.class)
를 하는 순간 NoSuchBeanDefinitionException
이 발생한다.
FilterType 옵션
- ANNOTATION: 기본값, 애노테이션을 인식해서 동작한다.
- 기본값이기 때문에, 위에서 작성한 코드에서 생략해도 잘 동작한다.
- Ex)
org.example.SomeAnnotation
- ASSIGNABLE_TYPE: 지정한 타입과 자식 타입을 인식해서 동작한다.
- Ex)
org.example.SomeClass
- Ex)
- ASPECTJ: AspectJ 패턴 사용
- Ex)
org.example..*Service+
- Ex)
- REGEX: 정규 표현식
- Ex)
org\.example\.Default.*
- Ex)
- CUSTOM: TypeFilter 이라는 인터페이스를 구현해서 처리
- Ex)
org.example.MyTypeFilter
- Ex)
@MyIncludeComponent
가 붙은 BeanA를 컴포넌트 스캔 대상에서 제외하고 싶다면, ASSIGNABLE_TYPE
을 사용해서 다음과 같이 해주면 된다.
ComponentFilterAppConfigTest.java
//package, import 생략
public class ComponentFilterAppConfigTest {
//테스트 메소드 생략
@Configuration
@ComponentScan(
includeFilters =
@ComponentScan.Filter(type = FilterType.ANNOTATION,
classes = MyIncludeComponent.class),
excludeFilters =
@ComponentScan.Filter(type = FilterType.ANNOTATION,
classes = MyExcludeComponent.class)
excludeFilters =
@ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE,
classes = BeanA.class) //BeanA 제외
)
static class ComponentFilterAppConfig {
}
}
*참고:
@Component
면 충분하기 때문에,includeFilters
를 사용할 일은 거의 없다.excludeFilters
는 여러가지 이유로 간혹 사용할 때가 있지만 많지는 않다.특히 최근 스프링 부트는 컴포넌트 스캔을 기본으로 제공하는데, 개인적으로는 옵션을 변경하면서 사용하기 보다는 스프링의 기본 설정에 최대한 맞추어 사용하는 것을 권장하고, 선호하는 편이다.
'Spring > Spring core basic' 카테고리의 다른 글
[Spring core basic] 32 - 다양한 의존관계 주입 방법 (0) | 2022.05.03 |
---|---|
[Spring core basic] 31 - 컴포넌트 스캔, 중복 등록과 충돌 (0) | 2022.05.03 |
[Spring core basic] 29 - 컴포넌트 스캔 범위와 기본 스캔 대상 (0) | 2022.05.02 |
[Spring core basic] 28 - 컴포넌트 스캔과 의존관계 자동 주입 (0) | 2022.05.02 |
[Spring core basic] 27 - @Configuration과 바이트코드 조작 (0) | 2022.05.02 |
댓글