지금까지는 스프링 빈을 등록할 때 자바 코드의 @Bean이나 xml의 <bean>을 통해 직접 등록할 스프링 빈을 나열했다. 하지만 이런 작업은 설정 파일이 커질 뿐더러 귀찮고 실수가 발생할 수 있다.
그래서 스프링은 설정 정보 없이도 자동으로 스프링 빈을 등록하는 컴포넌트 스캔 기능을 제공한다. 의존 관계를 자동 주입하는 @Autowired도 제공한다.
@Configuration// @Component가 붙은 객체를 찾아서 스프링 빈으로 등록해준다.@ComponentScan(// AppConfig.java와의 충돌을 피하기 위해// Configuration 타입의 애너테이션이 달린 것은 제외한다.// @Configuration에 들어가보면 @Component가 달려있어 스캔 대상이 되기 때문이다. excludeFilters = @ComponentScan.Filter(type =FilterType.ANNOTATION, classes =Configuration.class))publicclassAutoAppConfig {}
컴포넌트 스캔을 사용하려면 ComponentScan을 설정 정보에 붙여준다. 기존 AppConfig와는 다르게 @Bean으로 등록한 클래스가 없는 걸 볼 수 있다.
컴포넌트 스캔을 사용하면 @Configuration도 @Component가 붙어있어 자동으로 등록된다. 따라서 다른 설정 정보와 충돌을 피하기 위해 excludeFilters로 스캔 대상에서 제외한다.
@ComponentpublicclassMemoryMemberRepositoryimplementsMemberRepository {}@ComponentpublicclassRateDiscountPolicyimplementsDiscountPolicy{}@ComponentpublicclassOrderServiceImplimplementsOrderService {privatefinalMemberRepository memberRepository;privatefinalDiscountPolicy discountPolicy;// ac.getBean(MemberRepository.class)와 같은 동작을 한다. @AutowiredpublicOrderServiceImpl(MemberRepository memberRepository,DiscountPolicy discountPolicy) {this.memberRepository= memberRepository;this.discountPolicy= discountPolicy; }}@ComponentpublicclassMemberServiceImplimplementsMemberService {privatefinalMemberRepository memberRepository; @AutowiredpublicMemberServiceImpl(MemberRepository memberRepository) {this.memberRepository= memberRepository; }}
이제 사용하는 구현체에 @Component를 붙여준다. 이제는 AppConfig처럼 의존 관계를 반환해서 등록하는 메서드가 없기 때문에, 생성자에 @Autowired를 붙여 여러 의존 관계를 한 번에 주입받는다.
publicclassAutoAppConfigTest { @TestvoidbasicScan() {AnnotationConfigApplicationContext ac =newAnnotationConfigApplicationContext(AutoAppConfig.class);MemberService memberService =ac.getBean(MemberService.class);assertThat(memberService).isInstanceOf(MemberService.class); }}
AnnotationConfigApplicationContext를 사용하는 것은 기존과 동일하다. 설정 정보로 AutoAppConfig를 넘겨주면 기존과 같이 잘 동작한다.
로그를 보면 컴포넌트 스캔으로 의존성 주입이 잘 되는 것을 볼 수 있다.
@ComponentScan의 동작 방식
@ComponentScan이 되어있으면 스프링 컨테이너가 @Component가 붙은 모든 클래스를 스프링 빈으로 등록한다.