컴포넌트 스캔과 의존관계 자동 주입 시작하기
- 스프링 빈을 등록할 때 자바 코드의 @Bean이나 XML의 <bean> 태그를 통해서 설정 정보에 직접 등록할 스프링 빈을 나열
- 그런데 이렇게 등록해야할 빈이 수십, 수백 개가 되면 직접 등록하는 데에 한계가 있다.
- 스프링은 설정 정보가 없어도 자동으로 스프링 빈을 등록하는 컴포넌트 스캔이라는 기능 제공
- 의존관계를 자동으로 주입하는 @Autowired라는 기능을 제공한다.
컴포넌트 스캔
@Configuration
@ComponentScan(
//basePackages = "com.example.core.discount",
excludeFilters = @Filter(type = FilterType.ANNOTATION, classes =
Configuration.class)) //appconfig와 설정정보 겹치기 때문에 제외
public class AutoAppConfig {}
@ComponentScan 은 @Component 가 붙은 모든 클래스를 스프링 빈으로 등록한다
- 이제 각 클래스가 컴포넌트 스캔의 대상이 되도록 @Component 애노테이션을 붙여주면 된다.
MemoryMemberRepository @Component 추가
RateDiscountPolicy @Component 추가
@Configuration 이 컴포넌트 스캔의 대상이 된 이유도 @Configuration 소스코드를 열어보면 @Component 애노테이션이 붙어있기 때문이다.
@Autowired
@Component
public class MemberServiceImpl implements MemberService {
private final MemberRepository memberRepository;
@Autowired
public MemberServiceImpl(MemberRepository memberRepository) {
this.memberRepository = memberRepository;
}
}
@Autowired 는 의존관계를 자동으로 주입해준다.
@Autowired 를 사용하면 생성자에서 여러 의존관계도 한번에 주입받을 수 있다
탐색 위치와 기본 스캔 대상
탐색할 패키지의 시작 위치 지정
- 모든 자바 클래스를 다 컴포넌트에 스캔하면 시간이 오래 걸리기 때문에 필요한 위치부터 탐색하도록 시작 위치를 지정할 수 있다.
- backPackages : 탐색할 패키지의 시작 위치를 지정한다.
- 해석하자면, “hello.core” 패키지를 포함해서 하위 패키지를 모두 탐색한다는 의미이다.
- basePackages = {"hello.core", "hello.service"} 처럼 여러 시작 위치를 지정할 수도 있다.
@ComponentScan(
basePackageClasses = AutoAppConfig.class,
}
- basePackageClasses : 지정한 클래스의 패키지를 탐색 시작 위치로 지정한다.
- 패키지의 시작 위치를 지정하지 않으면 @ComponentScan이 붙은 설정 정보 클래스의 패키지가 시작 위치가 된다.
권장하는 방법은 패키지의 위치를 지정하지 않고,
설정 정보 클래스의 위치를 프로젝트 최상단에 두는 것이다. 스프링 부트도 이 방법을 기본으로 제공한다.
- 예를 들어 프로젝트가 다음과 같은 구조로 되어 있으면
- com.hello
- com.hello.service
- com.hello.repository
- com.hello 를 프로젝트 시작 루트로 하고, 여기에 AppConfig와 같은 메인 설정 정보를 두고, @ComponentScan 애노테이션을 붙이고, basePackages 지정은 생략한다.
- 그러면 com.hello 를 포함한 하위 패키지 모두 자동으로 컴포넌트 스캔의 대상이 된다.
컴포넌트 스캔 기본 대상
- 컴포넌트 스캔은 Component 뿐만 아니라 다음과 같은 내용도 추가로 대상에 포함한다.
- @Contoller : 스프링 MVC 컨트롤러에서 사용
- @Service : 스프링 비즈니스 로직에서 사용
- @Repository : 스프링 데이터 접근 계층에서 사용
- @Configuration : 스프링 설정 정보에서 사용
필터
- includeFilters : 컴포넌트 스캔 대상을 추가로 지정한다.
- excluderFilters : 컴포넌트 스캔에서 제외할 대상을 지정한다.
중복 등록과 충돌
- 컴포넌트 스캔에서 같은 빈 이름을 등록하는 두가지 상황이 있다. 결론적으로 둘다 오류가 발생한다.
- 자동 빈 등록 vs 자동 빈 등록 -> 같은 경우 스프링은 ConflictingBeanDefinitionException 와 같은 예외를 발생시킨다.
- 수동 빈 등록 vs 자동 빈 등록 -> 같은 경우 수동 빈 등록이 우선권을 가지면서 자동 빈을 오버라이딩 한다.
Consider renaming one of the beans or enabling overriding by setting
spring.main.allow-bean-definition-overriding=true
스프링 부트에서 수동 빈 등록과 자동 빈 등록이 충돌나면 오류가 발생하도록 기본 값
출처 : 김영한 스프링 핵심 원리
'프로그래밍 > Spring' 카테고리의 다른 글
[Spring] 8. 빈 생명주기 콜백 (0) | 2024.06.19 |
---|---|
[Spring] 7. 의존관계 자동 주입 (0) | 2024.06.19 |
[Spring] Section 5. 싱글톤 컨테이너 (0) | 2024.06.07 |
[Spring] Section 4. 스프링 컨테이너와 스프링 빈 (0) | 2024.06.06 |
[Spring] Section 3. 스프링 핵심 원리 이해2 - 객체 지향 원리 적용 (0) | 2024.06.06 |