[스프링 프레임워크 핵심기술] @ComponentScan

Dayeon myeong·2021년 2월 23일
0

1. @ComponentScan

@ComponentScan은 spring 3.1부터 도입되었으며 설정된 시작 지점부터 컴포넌트 클래스를 scanning하여 빈으로 등록해주는 역할을 한다.

빈으로 등록 될 수 있는 컴포넌트 클래스

  • @Component
  • @Repository
  • @Service
  • @Controller
  • @Configuration

@ComponentScan의 두가지 속성

  1. Component를 Scan할 시작 지점을 설정한다.
  2. @Filter로 scan한 Component 중 빈으로 등록하지 않을 클래스를 제외하거나 포함해줄 수 있다. (ex. excludeFilter, includeFilter)

Scan 시작 지점 설정 - basePackages()와 basePackageClasses()

basePackages()와 basePackageClasses()는 Component를 scan할 시작지점을 설정할 수 있다.

basePackages()에는 scan을 시작할 패키지를 문자열로 지정하여 해당 패키지 하위에 있는 패키지의 모든 component를 스캔할 수 있다.

아래와 같이 사용가능하다.

위와 같이 설정하면 scan 시작 패키지가 com.example.autowired이 된다. 해당 패키지와 하위 패키지의 모든 component를 scan해서 등록해준다.

하지만 basePackages()의 경우 직접 문자열을 적어야 하기 때문에 철자가 잘못되면 scan을 못하는 오류가 날 수 있다. 이는 typesafe하지 않다. 그래서 있는게 basePackageClasses!

basePackageClasses()에는 scan을 시작할 클래스 타입을 지정한다.

위와 같이 설정하면 마찬가지로 scan 시작 패키지가 AutowiredApplication 클래스가 포함된 패키지가 시작점이 된다.

basePackages()나 basePackageClasses()를 설정해주지 않으면 기본적으로 @ComponentScan이 붙어있는 configuration 클래스가 자동으로 시작 지점이 된다.

SpringBoot에서는 @SpringBootApplication 어노테이션에 @ComponentScan과 @EnableAutoConfiguration이 포함되어 있기 때문에 해당 어노테이션이 있는 패키지를 시작점으로 Component들을 빈으로 등록가능하다.

펑션을 사용한 빈 등록

다른 패키지에 있는 MyService 클래스를 빈으로 등록하고 싶을 때 펑션 사용

@SpringBootApplication
public class Demospring52Application {
 
    @Autowired
    MyService myService;
 
    public static void main(String[] args) {
        var app = new SpringApplication(Demospring52Application.class);
 
        app.addInitializers((ApplicationContextInitializer<GenericApplicationContext>) ctx -> {
            ctx.registerBean(MyService.class);
 
            // 메시지를 출력하는 ApplicationRunner를 생성해서 빈으로 등록
            ctx.registerBean(ApplicationRunner.class, () -> args1 -> System.out.println("Hello World!!"));
        });
 
        app.run(args);
    }
}

ComponentScan 방식과 펑션 방식

@ComponentScan 방식은 싱글톤 스코프인 빈들을 모두 초기에 생성하기 때문에 어플리케이션의 초기 구동시간이 오래 걸린다는 단점이 있다.

펑션을 사용한 빈 등록 방식은 @ComponentScan 방식보다 구동시간이 더 짧다. 게다가 조건에 따라 빈을 등록한다던지 등의 로직을 추가할 수 있다. 즉 빈을 등록하는데있어서 프로그래밍적인 컨트롤이 가능해진다.

두 방법은 동시에 사용이 가능하며 이 경우 다른 빈들을 등록하기 전에 @ComponentScan 방식으로 빈을 먼저 등록한다.

@ComponentScan은 BeanFactoryPostProcessor와 관련있는데 BeanFactoryPostProcessor의 실행 시점은 다른 모든 빈들을 만들기 이전에 적용된다. 즉, 다른 빈들을 등록하기 전에 @ComponentScan으로 빈을 먼저 등록한다.

이와 비슷하게 @SpringBootApplication의 경우에도 먼저 @ComponentScan 이후 @EnableAutoConfiguration으로 빈을 등록한다.

하지만 펑션 방식은 모든 빈을 직접 등록해줘야하기 때문에 코드가 복잡하고 매우 번거롭다. 그래서 @ComponentScan으로 등록하는 빈 외에 빈을 등록해야할 경우에는 펑션 방식을 사용할 순 있을 듯하다.

참고 자료
https://atoz-develop.tistory.com/entry/Spring-Component-Scan%EA%B3%BC-Function%EC%9D%84-%EC%82%AC%EC%9A%A9%ED%95%9C-%EB%B9%88-%EB%93%B1%EB%A1%9D-%EB%B0%A9%EB%B2%95

인프런 스프링 프레임워크 핵심 기술

profile
부족함을 당당히 마주하는 용기

0개의 댓글