본문 바로가기

SpringFramework Core - I. IoC 컨테이너/10. 클래스패스 스캐닝과 관리받는 컴포넌트들

10.6. 자동 탐지된 컴포넌트들에 이름 붙이기

원문: https://docs.spring.io/spring-framework/docs/current/spring-framework-reference/core.html#beans-scanning-name-generator

 

 

스캐닝 과정에서 컴포넌트가 자동으로 탐지될 때, 스캐너의 BeanNameGenerator 전략에 따라 bean의 이름이 생성된다. 기본적으로, 어떤 스프링 stereotype 어노테이션이든(@Component, @Repository, @Service) 이름 'value'를 가지고 있으며 그 덕분에 bean 정의에 이름을 부여할 수 있다. 

 

만약 그런 어노테이션들이 이름 'value'를 가지고 있지 않거나 탐지된 컴포넌트가 없다면, 기본 bean 이름 생성기가 소문자로 변환된 non-qualified한 이름을 반환해준다. 예를 들어, 다음 컴포넌트 클래스들이 탐지되면, 이름은 'myMovieLister'와 'movieFinderImpl'이 될 것이다.

@Service("myMovieLister")
public class SimpleMovieLister {
    // ...
}
@Repository
public class MovieFinderImpl implements MovieFinder {
    // ...
}

만약 기본적인 bean 이름 생성 전략에 의존하고 싶지 않다면, 커스텀한 bean 이름 생성 전략을 제공할 수 있다. 먼저, BeanNameGenerator 인터페이스를 구현한다. 이때, 매개변수가 없는 기본 생성자를 꼭 포함시켜야 한다. 그리고나서, 스캐너를 설정할 때 완전히 qualified된 클래스명을 제공한다. 다음 어노테이션과 bean 정의가 이를 보여준다.

만약 non-qualified된 클래스명이 같아서 탐지된 컴포넌트들 사이에 충돌이 발생한다면(다른 패키지에 있지만 같은 이름을 가진 클래스들처럼), 생성된 bean 이름에 qualified된 이름을 기본으로 제공하는 BeanNameGenerator를 설정할 필요가 있다. 스프링 프레임워크 5.2.3에서부터, org.springframework.context.annotation 패키지 안의 FullyQualifiedAnnotationBeanNameGenerator를 그 목적을 위해서 사용할 수 있다.
@Configuration
@ComponentScan(basePackages = 'org.example", nameGenerator = MyNameGenerator.class)
public class AppConfig {
    // ...
}
<beans>
    <context:component-scan base-package="org.example"
        name-generator="org.example.MyNameGenerator" />
</beans>

기본적인 규칙상, 다른 컴포넌트들이 명확하게 이름을 참조하고 있을 때는 어노테이션을 통해 이름을 확정하도록 하자. 한편, 자동 생성된 이름은 컨테이너가 wiring을 하는 것에 있어 적절하다.