꼬물꼬물
컴포넌트 스캔 [의존관계 자동 주입, 탐색 위치와 기본 스캔 대상] 본문
컴포넌트 스캔과 의존관계 자동 주입하기
- 지금까지 @Configuration, @Bean이나 XML의 <bean>을 통해 설정 정보에 직접 등록할 스프링 빈을 나열했따.
- 설정 정보가 커지고, 누락, 반복으로 더 나은 방법을 찾아보자
- 스프링은 설정 정보가 없어도 자동으로 스프링 빈을 등록하는 컴포넌트 스캔이라는 기능을 제공한다!
- 또한 의존관계도 자동으로 주입하는 @Autowired 기능도 제공한다.
@Configuration // 설정 정보
@ComponentScan(
excludeFilters = @ComponentScan.Filter(type = FilterType.ANNOTATION, classes = Configuration.class)
// @Configuration이 붙은 클래스는 제외한다.
) // @Component가 붙은 클래스를 찾아 자동으로 스프링 빈을 등록해준다.
public class AutoAppConfig {
}
- 컴포넌트 스캔을 사용하려면 @ComponentScan을 설정 정보에 붙여준다.
- 기존의 AppConfig(수동)와 달리 @Bean으로 등록한 클래스가 없다!
- @Configuration은 @Component를 포함하기 때문에 자동 등록된다. 이미 만들어둔 수동 설정이 들어갈 수 있어 excludeFilters를 이용해 스캔 대상 제외하기. <- 기존 코드 유지를 위해 사용
빈에 등록해야하는 MemoryMemberRepository, RateDiscountPolicy, MemberServiceImpl에 @Component를 붙인다.
@Component
public class MemberServiceImpl implements MemberService{
private final MemberRepository memberRepository;
@Autowired //ac.getBean(MemberRepository.class)
public MemberServiceImpl(MemberRepository memberRepository){
this.memberRepository = memberRepository;
}
}
Config 파일이 비어있는데 의존관계 주입을 어떻게 할까?
- @Autowired를 생성자에 붙이면 MemberRepository에 맞는 빈을 찾아와서 자동으로 연결해 주입한다.(자동 의존관계 주입)
- == ac.getBean(MemberRepository.class)와 같다
- 이전 AppConfig는 @Bean으로 직접 설정 정보를 작성했고, 의존관계도 직접 명시했다.
- ComponentScan을 사용하면 이런 설정 정보 자체가 없기 때문에, 의존관계 주입도 해당 클래스 내에서 해결해야 한다.
- @Autowired는 의존관계를 자동으로 주입한다.
@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;
}
}
- @Autowired를 사용하면 생성자에서 여러 의존관계도 한번에 주입받을 수 있다.
테스트하기
public class AutoAppConfigTest {
@Test
void basicScan(){
ApplicationContext ac = new AnnotationConfigApplicationContext(AutoAppConfig.class);
MemberService memberService = ac.getBean(MemberService.class);
assertThat(memberService).isInstanceOf(MemberService.class);
}
}
- (A, 자식).isInstanceOf(B, 부모): A가 B 타입으로 받을 수 있는지
- 설정 정보를 AutoAppConfig 클래스를 넘겨준다.
1. @ComponentScan
- @ComponentScan은 @Component가 붙은 모든 클래스를 스프링 빈으로 등록한다. 모든 클래스를 다 뒤진다.
- 스프링 빈의 기본 이름은 클래스명, 맨 앞글자는 소문자.
- 빈 이름 기본 전략: MemberServiceImple -< memberServiceImpl
- 빈 이름 직접 지정: 이름을 지정하고 싶으면 @Component(MemberService에 의미 부여
2. @Autowired 의존관계 자동 주입
- 생성자에 @Autowired로 지정하면, 스프링 컨테이너가 자동으로 해당 스프링 빈을 찾아서 주입한다.
- 이때 기본 조회 전략은 타입이 같은 빈을 찾아서 주입한다.
- getBean(MemberRepository.class)와 동일
- 타입이 같은게 여러개라면....!?!?
탐색 위치와 기본 스캔 대상
탐색할 패키지의 시작 위치 지정
모든 자바 클래스를 다 컴포넌트로 지정하면 시간이 오래걸린다. 꼭 필요한 위치부터 탐색하도록 시작 위치를 지정할 수 있다.
package hello.core;
@Configuration // 설정 정보
@ComponentScan(
basePackages = "hello.core.member",
basePackageClass = AutoAppConfig.class,
excludeFilters = @ComponentScan.Filter(type = FilterType.ANNOTATION, classes = Configuration.class) // @Configuration이 붙은 클래스는 제외한다.
) // @Component가 붙은 클래스를 찾아 자동으로 스프링 빈을 등록해준다.
public class AutoAppConfig {
}
- basePackages: 탐색할 패키지의 시작 위치를 지정한다. 이 패키지를 포함해 하위 패키지를 모두 탐색한다.
- basePackages = {"hello.core", "hello.service"} 패키지 여러 시작 위치를 지정할 수 있다.
- basePackageClasses: 지정한 클래스의 패키지를 탐색 시작 위로 지정한다. == hello.core
- 만약 지정하지 않으면 @ComponentScan이 붙은 설정 정보 클래스의 패키지가 시작 위치가 된다.
- 즉 AutoAppConfig가 패키지 시작 위치가 된다.
권장: 패키지 위치를 지정하지 않고, 설정 정보 클래스의 위치를 프로젝트 최상단에 둔다. == hello.core
ex) com.hello, com.hello.service, com.hello.repository 등의 프로젝트 구조가 있다면
com.hello -> 프로젝트 시작 루트, 여기에 AppConfig와 같은 메인 설정 정보를 두고, @ComponentScan 애노테이션을 붙여 basePackages를 생략한다.
com.hello를 포함한 하위가 모두 자동으로 컴포넌트 스캔의 대상이 된다.
프로젝트 메인 설정 정보는 프로젝트를 대표하는 정보이기 때문에 프로젝트 시작 루트 위치에 두는 것이 좋다.
스프링 부트에서는 대표 시작 정보인 @SpringBootApplication을 이 프로젝트 시작 위치에 두는 것이 관례이다.
컴포넌트 스캔 기본 대상
컴포넌트 스캔은 @Component 뿐만 아니라 추가적인 대상이 존재한다.
- @Component: 컴포넌트 스캔에서 사용
- @Controller: 스프링 MVC 컨트롤러에서 사용
- @Service: 스프링 비즈니스 로직에서 사용
- @Repository: 스프링 데이터 접근 계층에서 사용
- @Configuration: 스프링 설정 정보에서 사용
Service, Repository, Configuration 등 모두 @Component를 가지고 있다.
사실 애노테이션은 상속관계가 없다. 애노테이션이 특정 애노테이션을 들고 있는 것을 인식할 수 있는 것은 자바가 아닌 스프링이 지원하는 기능이다.
부가 기능
- @Controller: 스프링 MVC 컨트롤러로 인식
- @Service: 특별한 처리는 하지 않는다. 대신 개발자들이 핵심 비즈니스 로직의 위치를 찾도록 비즈니스 계층을 인식하는데 도움을 준다.
- @Repository: 스프링 데이터 접근 계층으로 인식, 데이터 계층의 예외(ex. DB 예외)를 스프링 예외로 변환해준다.
- @Configuration: 스프링 설정 정보로 신식하고, 스프링 빈이 싱글톤을 유지하도록 추가 처리를 한다.
'스터디 > 스프링 핵심 원리 - 기본편' 카테고리의 다른 글
의존관계 자동 주입 [다양한 의존관계 주입 방법] (0) | 2022.09.25 |
---|---|
컴포넌트 스캔 [필터, 중복 등록과 충돌] (0) | 2022.09.22 |
싱글톤 컨테이너 [@Configuration] (0) | 2022.09.18 |
싱글톤 컨테이너 [싱글톤 컨테이너] (0) | 2022.09.17 |
싱글톤 컨테이너 [싱글톤 패턴] (0) | 2022.09.17 |