[SPRING] 컴포넌트 스캔과 의존관계 자동 주입
직접 @Bean을 붙여 스프링 빈을 등록하는건 너무너무 귀찮다!
자동으로 빈을 등록하고 의존 관계를 주입하는 방법에 대해 알아보자.
package hello.core;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.FilterType;
import static org.springframework.context.annotation.ComponentScan.*;
@Configuration
@ComponentScan(
excludeFilters = @Filter(type = FilterType.ANNOTATION, classes =
Configuration.class))
public class AutoAppConfig {
}
@ComponentScan은 @Component 어노테이션이 붙은 클래스를 스캔해 자동으로 그 클래스를 스프링 빈으로 등록한다.
@Component
public class OrderServiceImpl implements OrderService {
private final MemberRepository memberRepository;
private final DiscountPolicy discountPolicy;
@Autowired
public OrderServiceImpl(MemberRepository memberRepository, DiscountPolicy discountPolicy) {
this.memberRepository = memberRepository;
this.discountPolicy = discountPolicy;
}
}
하지만 @Component를 모든 스프링 빈 클래스에 붙여주고 Config 클래스에서 의존관계 주입 메소드를 삭제한다면.. OrderServiceImpl에서 사용할 memberRepository와 discountPolicy의 의존관계는 누가 주입하는걸까?
정답: 의존관계 주입에 사용되는 생성자에 @Autowired 어노테이션을 추가해주면 자동으로 의존관계가 주입된다. 스프링 빈은 memberRepository라는 이름으로 등록된 스프링 빈을 찾아 자동으로 OrderServiceImpl 생성자의 memberRepository 파라미터에 주입한다.
이렇듯 스프링 컨테이너는 @Component가 붙은 클래스를 찾아 클래스명의 앞글자만 소문자로 바꿔 빈 객체로 등록한다. 이름을 임의로 설정하고 싶다면 @Component("이름")으로 설정하도록 한다.
의존관계는 해당 타입의 스프링 빈 객체를 찾아 스프링 컨테이너가 자동으로 주입한다. (타입이 중복되면 오류 발생)
Component Scan의 탐색 위치와 기본 스캔 대상
- 스캔의 시작 위치 지정 방법
@ComponentScan(
basePackages = "hello.core",
}
시작 위치를 지정하지 않으면 기본적으로 해당 설정 클래스의 위치부터 스캔하기 시작한다. 그래서 AppConfig 같은 메인 설정 정보는 프로젝트의 시작 루트에 두는 것을 추천한다.(ex: 'com.example')
사실 기본적으로 @ComponentScan은 프로젝트의 시작 루트에 있는 @SpringBootApplication 어노테이션에 들어가 있기 때문에 따로 AppConfig에 @ComponentScan을 붙이지 않아도 된다.
컴포넌트 스캔 기본 대상
- @Component
- @Controller: 스프링 MVC 컨트롤러로 인식
- @Repository: 스프링 데이터 접근 계층으로 인식
- @Configuration: 스프링 설정 정보로 인식
- @Service: 특별한 처리는 없지만 개발자들간의 약속? 핵심 비즈니스 로직이 여기 있겠구나.. 라고 인식
사실 모두 @Component를 포함하고 있다.
필터
- includeFilters: 컴포넌트 스캔 대상을 추가 지정
- excludeFilters: 컴포넌트 스캔에서 제외할 대상 지정
참조: