본문 바로가기
스프링/핵심 원리

[Spring] 필터

by drCode 2022. 2. 17.
728x90
반응형
  • includeFilters : 컴포넌트 스캔 대상을 추가로 지정한다.
  • excludeFilters : 컴포넌트 스캔에서 제외할 대상을 지정한다.

 

빠르게 예제로 확인해보자.

"모든 코드는 테스트 코드에 추가"

 

위의 경로에 Annotation으로 만들어준다. MyIncludeComponent.java

 

 

MyIncludeComponent.java

package hello.core.scan.filter;

import java.lang.annotation.*;

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface MyIncludeComponent {
}

 

MyExcludeComponent.java

package hello.core.scan.filter;

import java.lang.annotation.*;

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface MyExcludeComponent {
}

 

BeanA.java

package hello.core.scan.filter;

@MyIncludeComponent
public class BeanA {
}

 

BeanB.java

package hello.core.scan.filter;

@MyExcludeComponent
public class BeanB {
}

 

ComponentFilterAppConfigTest.java

package hello.core.scan.filter;


import org.assertj.core.api.Assertions;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.FilterType;

import static org.springframework.context.annotation.ComponentScan.*;
import static org.assertj.core.api.Assertions.*;

public class ComponentFilterAppConfigTest {

    @Test
    void filterScan() {
        ApplicationContext ac = new AnnotationConfigApplicationContext(ComponentFilterAppConfig.class);
        BeanA beanA = ac.getBean("beanA", BeanA.class);
        assertThat(beanA).isNotNull();

        org.junit.jupiter.api.Assertions.assertThrows(
                NoSuchBeanDefinitionException.class,
                () -> ac.getBean("beanB", BeanB.class));
    }


    @Configuration
    @ComponentScan(
            includeFilters = @Filter(type = FilterType.ANNOTATION, classes = MyIncludeComponent.class),
            excludeFilters = @Filter(type = FilterType.ANNOTATION, classes = MyExcludeComponent.class)

    )
    static class ComponentFilterAppConfig {

    }
}
  • includeFilters에 MyIncludeComponent 애노테이션을 추가해서 BeanA가 스프링 빈에 등록된다.
  • excludeFilters에 MyExcludeComponent 애노테이션을 추가해서 BeanB는 스프링 빈에 등록되지 않는다.

 

FilterType 옵션

FilterType은 5가지 옵션이 있다.

 

  • ANNOTATION : 기본값, 애노테이션을 인식해서 동작한다.
    • ex) 'org.example.SomeAnnotation'
  • ASSIGNABLE_TYPE : 지정한 타입과 자식 타입을 인식해서 동작한다.
    • ex) 'org.example.SomeClass'
  • ASPECTJ : AspectJ 패턴 사용
    • ex) 'org.example..*Service+'
  • REGEX : 정규표현식
    • ex) 'org\.example\.Default.*'
  • CUSTOM : 'TypeFilter'이라는 인터페이스를 구현해서 처리
    • ex) 'org.example.MyTypeFilter'

예를 들어서 BeanA도 빼고 싶으면 다음과 같이 추가하면 된다.

@ComponentScan(
        includeFilters = {
        	@Filter(type = FilterType.ANNOTATION, classes = MyIncludeComponent.class), 
        },
        excludeFilters = {
        	@Filter(type = FilterType.ANNOTATION, classes = MyExcludeComponent.class),
            @Filter(type = FilterType.ASSIGNABLE_TYPE, classes = BeanA.class)
		}
)

 

참고 : @Component면 충분하기 때문에, includeFilters를 사용할 일은 거의 없다. excludeFilters는 여러가지 이유로 간혹 사용할 때가 있지만 많지는 않다.

특히 최근 스프링 부트는 컴포넌트 스캔을 기본으로 제공하는데, 개인적으로는 옵션을 변경하면서 사용하기 보다는 스프링의 기본 설정에 최대한 맞추어 사용하는 것을 권장하고, 선호하는 편이다.

728x90
반응형

댓글