스프링 컴포넌트 스캔

Red Culture·2021년 9월 6일
0

컴포넌트 스캔이란

@Bean을 통해 설정 정보에 스프링 빈을 등록할 때 수십, 수백개가 되면 일일히 등록하는 것이 번거롭고, 누락이 생기기 쉽기 때문에 이러한 불편함을 줄이기 위해 스프링은 설정 정보가 없어도 자동으로 스프링 빈을 등록하는 컴포넌트 스캔이라는 기능을 제공한다.
컴포넌트 스캔 시 @Component 어노테이션이 붙은 클래스를 스캔해서 스프링 빈으로 등록한다.

스프링 빈 등록 시 빈의 기본 이름은 클래스명을 사용하되 맨 앞글자만 소문자를 사용한다. (ex) OrderServiceImpl 클래스 -> orderServiceImpl)
스프링 빈의 이름을 직접 지정하고 싶으면 @Component("부여하고 싶은 이름") 으로 작성하면 된다.

스프링 컨테이너에 자동으로 빈을 등록하면 의존관계를 주입할 수 있는 방법이 없다. 전에는 하나하나 getBean을 통해 의존관계를 수동으로 설정했지만, 컴포넌트 스캔은 설정 정보 자체를 안쓰기 때문이다. 그래서 의존관계 자동 주입을 사용해서 주입을 해야한다.

@Autowired 의존관계 자동 주입

생성자에 @Autowired를 지정하면 스프링 컨테이너가 자동으로 해당 스프링 빈을 찾아서 주입한다. 기본적으로 타입이 같은 빈을 찾아서 주입한다. 생성자에 파라미터가 많아도 다 찾아서 자동으로 주입한다.

컴포넌트 스캔 탐색, 기본 대상

@Configuration
@ComponentScan(
        // 컴포넌트 스캔할 때 탐색할 패키지의 시작 위치를 지정하고, 이 패키지를 포함한 하위 패키지를 모두 탐색한다.
        basePackages = "hello.core.member",
        // 지정한 클래스의 패키지를 탐색 시작 위치로 지정한다.
        basePackageClasses = AutoAppConfig.class,
        // 따로 패키지를 지정하지 않으면 디폴트로 @ComponentScan를 붙인 클래스의 패키지를 시작 위치로 이 패키지를 포함한 하위 패키지를 모두 탐색한다. (여기서는 hello.core가 시작 위치)
        // 컴포넌트 스캔할 때 스프링 빈을 등록할 때 제외할 것 지정
        excludeFilters = @ComponentScan.Filter(type = FilterType.ANNOTATION, classes = Configuration.class)
)
public class AutoAppConfig {
}

스프링부트는 @SpringBootApplication를 프로젝트 시작 루트 위치에 두어 설정 안에 @ComponentScan이 들어 있어 자동으로 스프링 빈이 등록되기 때문에 별도로 사용할 필요가 없다.

includeFilters, excludeFilters를 사용해서 어노테이션을 정의하고 추가해서 스프링 빈에 등록하거나 등록하지 않도록 설정할 수 있다.

public class ComponentFilterAppConfigTest {

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

        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 {
    }
}

자동으로 빈을 등록했는데 수동으로도 빈이 등록되어 이름이 중복되는 경우에는 수동 빈 등록이 우선권을 갖는다. (수동 빈이 자동 빈을 오버라이딩한다.)
스프링부트에서는 수동 빈 등록과 자동 빈 등록 충돌 시 오류를 발생하도록 설정되어 있다.
만약.. 중복 등록을 허용하려면 application.properties에 spring.main.allow-bean-definition-overriding=true 설정하면 된다.

*참고 자료
스프링 핵심 원리 (김영한님)

profile
자기 개발, 학습 정리를 위한 블로그

0개의 댓글