보름달빵 2024. 2. 25. 17:02

 

앞에서 컴포넌트 스캔 대상이 되는 몇 가지 어노테이션이 있었다. 

그렇다면 해당 어노테이션이 아니더라도 컴포넌트 스캔 대상이 되도록 할 수는 없을까? 

 

바로 이 기능을 담당하는 것이 필터이다. 

 

우리가 일상생활에서 쓰는 필터는  '걸러내는 틀'  이다. 

 

이것을 스프링의 관점으로 생각해본다면  필터란 무엇을 빈으로 등록하고, 등록하지 않을지 걸러내는 것 이다. 

 

 

 

 


 

 

필터

 

컴포넌트 스캔 대상에 추가할 어노테이션

package hello.core.scan.filter;

import java.lang.annotation.*;

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface MyIncludeComponent {
    //@MyIncludeComponent : 컴포넌트 스캔 대상
}

 

 

컴포넌트 스캔 대상에서 제외할 어노테이션

package hello.core.scan.filter;

import java.lang.annotation.*;

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface MyExcludeComponent {
    //@MyExcludeComponent : 컴포넌트 스캔 대상 제외
}

 

 

 

컴포넌트 스캔 대상에 추가할 클래스

package hello.core.scan.filter;

@MyIncludeComponent
public class BeanA {
}

 

 

 

컴포넌트 스캔 대상에서 제외할 클래스

package hello.core.scan.filter;

@MyExcludeComponent
public class BeanB {
}

 

 

 

 

실행 정보와 전체 테스트 코드

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.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.FilterType;

import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.jupiter.api.Assertions.*;

public class ComponentFilterAppConfigTest {

    @Test
    void filterScan(){
    
        AnnotationConfigApplicationContext ac = 
                new AnnotationConfigApplicationContext(ComponentFilterAppConfig.class);
                
        //beanA는 스프링 빈으로 등록됨
        BeanA beanA = ac.getBean("beanA", BeanA.class);

        assertThat(beanA).isNotNull();

        //beanB는 스프링 빈으로 등록X -> beanB 조회시 예외발생
        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{
          // @Component + @MyIncludeComponent 를 빈으로 등록
    }
}

 

  • includeFilters : 컴포넌트 스캔 대상을 추가로 지정
  • excludeFilters : 컴포넌트 스캔에서 제외할 대상을 지정 

 

 

FilterType 옵션