원글 페이지 : 바로가기
컴포넌트 스캔 @Component를 가진 모든 대상을 가져와 Bean에 등록하기 위해 찾는 과정을 말한다. 즉, 빈 설정 파일과 @Bean을 통해 빈을 일일이 지정할 필요가 없다. 즉, 명시적인 등록과 달리, 자동으로 빈을 등록하는 방법이다. 1. xml 파일에 설정하기
@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