@Configuration
public class AppConfig {
@Bean
public MemberService memberService() {
return new MemberServiceImpl(memberRepository());
}
기존의 AppConfig에서 Bean 등록을 할때는 Bean Annotation을 붙여서 해결했다.
만약 이 빈이 5만개 있다면, 그걸 하나씩 다 등록하기에는 너무 귀찮고 관리도 어려울것이다.
그래서 나온게 컴포넌트 스캔이다.
@Configuration
@ComponentScan(
// basePackages = "hello.core.member",
excludeFilters = @ComponentScan.Filter(type = FilterType.ANNOTATION, classes = Configuration.class)
) // Configuration 빼고 자동스캔
public class AutoAppConfig {
}
자동으로 Component라는 Annotation이 붙은것들을 스캔한다.
@Component
public class MemoryMemberRepository implements MemberRepository {
이런식으로 붙이면 된다.
하지만 이러면, DI는 어떻게 처리되는걸까?
예를 들어, OrderServiceImpl을 보겠다.
@Component
public class OrderServiceImpl implements OrderService{
private final MemberRepository memberRepository;
private final DiscountPolicy discountPolicy;
public OrderServiceImpl(MemberRepository memberRepository, DiscountPolicy discountPolicy) {
this.memberRepository = memberRepository;
this.discountPolicy = discountPolicy;
}
이런식으로 생성자에 넣어줄 값이 AutoAppConfig에는 전혀 지정되어 있지 않다.
이러한 문제는 AutoWired Annotation으로 해결 할 수 있다.
@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하면, 스프링이 알아서 잡아서 넣어준다.
다른 방식은 [이 글]을 보자
컴포넌트 스캔은 기본적으로 자신의 디렉토리와 그 하위 모든 디렉토리이다.
통상적으로 Package 최상위루트에 Config를 만들어서 전체스캔을 한다.
또는 exclude 옵션을 통해 스캔하지 않을 클래스를 지정할 수 있다.
incldueFilter, excludeFilter를 통해서 필터옵션을 줄 수 있다.
필터 옵션은
ANNOTATION: 기본값, 애노테이션을 인식해서 동작한다.
ASSIGNABLE_TYPE: 지정한 타입과 자식 타입을 인식해서 동작한다.
ASPECTJ: AspectJ 패턴 사용
REGEX: 정규 표현식
CUSTOM: TypeFilter 이라는 인터페이스를 구현해서 처리
가 있다.
이 경우 ConflictingBeanDefinition 오류메세지가 나온다.
그냥 이름만 안겹치게 해주면 된다.
이 경우 문제없이 실행이 된다. 이 경우 수동등록 빈이 우선권을 가지고 overring 해버린다.
그리고 스프링에서 Overriding 메세지가 나온다.
다만, 현업에서는 설정이 꼬여서 이러한 의도하지 않은 오버라이딩이 나올 수 있고, 이런 버그들은 찾을 수가 없다.
따라서 이런 애매한 상황을 안만들도록 하는게 제일 좋고,
이에 결국 스프링부트에서 중복상황에 오류를 뱉어내도록 바뀌었다.