[Spring] 컴포넌트 기본 스캔 대상과 필터

Narcoker·2023년 8월 13일

Spring

목록 보기
9/19

컴포넌트 스캔 기본 대상

컴포넌트 스캔은 @Component 뿐만 아니라 다음과 내용도 추가로 대상에 포함한다.

@Component

컴포넌트 스캔에서 사용

@Controller

스프링 MVC 컨트롤러에서 사용
스프링 MVC 컨트롤러로 인식

@Service

스프링 비즈니스 로직에서 사용
@Service 는 특별한 처리를 하지 않는다.
대신 개발자들이 핵심 비즈니스 로직이 여기에 있겠구나 라고 비즈니스 계층을 인식하는데 도움이 된다.

@Repository

스프링 데이터 접근 계층에서 사용
스프링 데이터 접근 계층으로 인식하고, 데이터 계층의 예외를 스프링 예외로 변환해준다.

@Configuration

스프링 설정 정보에서 사용
스프링 설정 정보로 인식하고, 스프링 빈이 싱글톤을 유지하도록 추가 처리를 한다.

참고

useDefaultFilters 옵션은 기본으로 켜져있는데,
이 옵션을 끄면 기본 스캔 대상들이 제외된다. 그냥 이런 옵션이 있구나 정도 알고 넘어가자.

필터

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

커스텀 애노테이션 만들기

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

package hello.core.scan.filter;

import java.lang.annotation.*;

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

컴포넌트 대상에서 제외할 애노테이션

package hello.core.scan.filter;

import java.lang.annotation.*;

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

스캔 대상 만들어서 애노테이션 적용하기

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

@MyIncludeComponent 적용

package hello.core.scan.filter;

@MyIncludeComponent
public class BeanA {
}

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

@MyExcludeComponent 적용

package hello.core.scan.filter;
@MyExcludeComponent
public class BeanB {
}

테스트 코드

includeFiltersMyIncludeComponent 애노테이션을 추가해서 BeanA가 스프링 빈에 등록된다.
excludeFiltersMyExcludeComponent 애노테이션을 추가해서 BeanB는 스프링 빈에 등록되지 않는다.

package hello.core.scan.filter;

import org.junit.jupiter.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.assertj.core.api.Assertions.assertThat;
import static org.springframework.context.annotation.ComponentScan.Filter;

public class ComponentFilterAppConfigTest {
     @Test
     void filterScan() {
         ApplicationContext ac = new AnnotationConfigApplicationContext(ComponentFilterAppConfig.class);
         BeanA beanA = ac.getBean("beanA", BeanA.class);
         assertThat(beanA).isNotNull();
         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 {
	} 
}

FilterType 옵션

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

profile
열정, 끈기, 집념의 Frontend Developer

0개의 댓글