[Tistory] [Spring] 컴포넌트 스캔(Component Scan)

원글 페이지 : 바로가기

컴포넌트 스캔 @Component를 가진 모든 대상을 가져와 Bean에 등록하기 위해 찾는 과정을 말한다. 즉, 빈 설정 파일과 @Bean을 통해 빈을 일일이 지정할 필요가 없다. 즉, 명시적인 등록과 달리, 자동으로 빈을 등록하는 방법이다. 1. xml 파일에 설정하기 2. Java 파일 안에서 설정하기 (*실무에서 많이 쓰는 방법) @Configuration
@ComponentScan(basePackages = “com.dx”)
public class AppConfig {
} 컴포넌트 스캔 대상 @Component : 컴포넌트 스캔에서 사용한다. @Controller : Spring MVC Controller에서 사용한다. @Service : Spring Business 로직에서 사용한다. @Repository : Spring Data Access 계층에서 사용한다. @Configuration : Spring 설정 정보에서 사용한다. 아래 클래스 코드를 살펴보면 @Component를 포함하고 있다. (*이 상속 관계는 Spring 지원 기능, Java의 문법 X) @Component
public @interface Controller {

}

@Component
public @interface Repository {

}

@Component
public @interface Configuration {

} @ComponentScan 이 어노테이션이 있는 파일의 패키지 아래를 스캔한다. 탐색 위치 basePackages를 사용하면 탐색할 패키지 시작 위치를 지정한다. 이 패키지를 포함하여 하위 패키지를 모두 탐색한다. basePackageClasses를 사용하면 지정한 클래스가 있는 패키지를 시작 패키지로 설정한다. @ComponentScan (
    basePackages = “com.dx.springEx”
    // basePackages = {“com.dx.springEx01”, “com.dx.springEx02”} 여러 개도 지정 가능하다.
) 권장 방법 구성 파일에 등록한다면 패키지 위치를 지정하지 않고, 설정 정보 클래스 위치를 Project 최상단에 둔다. 만약, Spring Boot를 사용한다면 @SpringBootApplication 안에 @ComponentScan이 포함되어 있으므로 자동으로 최상단으로 유지가 된다. 만약, 프로젝트 구조가 아래와 같다면, 1) com.dx 2) com.dx.service 3) com.dx.controller 4) com.dx.repository ~~~ 1)번인 com.dx가 프로젝트 시작 루트이다. 이 위치에 AppConfig.java 로의 설정 정보 파일을 두고, @ComponentScan을 설정하면 된다. 결국 com.hello를 포함한 하위 패키지는 모두 컴포넌트 스캔의 대상이 된다. @Autowired 이 어노테이션을 활용하여 생성자에 지정하면 스프링 컨테이너가 자동으로 조건에 맞는 Type을 찾아 의존성 주입을 자동으로 해준다. 필터 includeFilters : 컴포넌트 스캔 대상을 추가로 지정한다. excludeFilters : 컴포넌트 스캔에서 제외할 대상을 지정한다. 필터 등록 방법 1. 커스텀 어노테이션 정의 // 컴포넌트 스캔 대상에 추가
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface MyIncludeComponent {
}

// 컴포넌트 스캔 대상에서 제외
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface MyExcludeComponent {
} 2. 커스텀 어노테이션 대상 클래스에 적용 @MyIncludeComponent
public class ExampleA { // 컴포넌트 스캔 대상에서 추가
}

@MyExcludeComponent
public class ExampleB { // 컴포넌트 스캔 대상에서 제외
} 3. 컴포넌트 스캔 필터 설정 @Configuration
@ComponentScan(
    excludeFilters = @Filter(type = FilterType.ANNOTATION, classes = MyExcludeComponent.class),
    includeFilters = @Filter(type = FilterType.ANNOTATION, classes = MyIncludeComponent.class))
static class ComponentFilterAppConfig {

} 4. 테스트 코드 public class ComponentFilterAppConfigTest {
    @Test
    public void filterScan() {
        
        // 애플리케이션 컨텍스트 로드
        ApplicationContext ac = new AnnotationConfigApplicationContext(
            ComponentFilterAppConfig.class);
        
        // ExampleA 타입의 빈을 가져온다.
        ExampleA exampleA = ac.getBean(ExampleA.class);
        
        // ExampleB 타입의 빈을 가져오려고 시도할 때 발생하는 예외를 캡처한다.
        Throwable throwable = Assertions.catchThrowable(() -> ac.getBean(ExampleB.class));

        // ExampleA 빈이 컨텍스트에 존재함을 확인한다.
        Assertions.assertThat(exampleA).isNotNull();
        
        // ExampleB 빈을 가져올 때 NoSuchBeanDefinitionException이 발생했음을 확인한다.
        Assertions.assertThat(throwable).isInstanceOf(NoSuchBeanDefinitionException.class);

    } 참고 자료 내용 참고 : 인프런 김영한 님의 강의 “스프링 핵심 원리 – 기본편” https://blogshine.tistory.com/217 https://velog.io/@hyun-jii/%EC%8A%A4%ED%94%84%EB%A7%81-component-scan-%EA%B0%9C%EB%85%90-%EB%B0%8F-%EB%8F%99%EC%9E%91-%EA%B3%BC%EC%A0%95 https://velog.io/@neity16/Spring-%ED%95%B5%EC%8B%AC-%EC%9B%90%EB%A6%AC-%EA%B8%B0%EB%B3%B8%ED%8E%B8-6-%EC%BB%B4%ED%8F%AC%EB%84%8C%ED%8A%B8-%EC%8A%A4%EC%BA%94Component-Scan-DI

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다