본문 바로가기

web +a

컴포넌트 스캔

∨ 등록해야할 스프링빈이 엄청 많아지면 @Bean으로 다 등록해주기가 까다로워짐

=> 스프링이 컴포넌트 스캔 기능 제공

 


이전 : @Configuration에서 @Bean을 통한 수동 bean 등록

- 의존관계가 직접 명시되어있었다.

 

지금 하는 거 : @ComponentScan을 통한 자동 bean 등록 (즉, @Bean 사용X)

- @Component가 붙은 클래스들을 스캔 -> 스프링빈으로 등록

- 각 빈에 대해 의존관계를 명시하지 않는다

=> 그럼 어떻게 DI 주입?

=> @Autowired가 의존관계를 자동으로 주입해준다. 

 

 예시

더보기

① 컴포넌트 스캔 기능을 이용하기 위해서

@ComponentScan을 붙인 설정정보(@Configuration) AutoAppConfig를 만들었다.

cf. 저 excludeFilters는 그냥.. 이전 실습한 수동 설정정보 빼주려고 붙인 거다.

@Configuration
@ComponentScan(
        excludeFilters = @ComponentScan.Filter(type = FilterType.ANNOTATION, classes = Configuration.class))
public class AutoAppConfig {
    
}

 

 

② 스캔의 대상이 되는 클래스(스프링빈으로 등록할 것)에 @Component를 붙여주었다.

@Component
public class RateDiscountPolicy implements DiscountPolicy{
   ...
}
@Component
public class MemoryMemberRepository implements MemberRepository{
   ...
}
@Component
public class MemberServiceImpl implements MemberService{
    ...
}
@Component
public class OrderServiceImpl implements OrderService{
    ...
}

 

 

③ 의존관계 자동 주입을 위해 @Autowired를 사용했다.

저렇게 생성자에 @Autowired 붙여주면, 필요한 애를 자동으로 찾아와서 주입해준다.

cf) ac.getBean(MemberRepository.class)처럼 찾아오는 원리다.

@Component
public class MemberServiceImpl implements MemberService{

    private final MemberRepository memberRepository;

    @Autowired
    public MemberServiceImpl(MemberRepository memberRepository) {
        this.memberRepository = memberRepository;
    }
    ....
}
@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;
    }
    ...
}

 

● 테스트

더보기
public class AutoAppConfigTest {

    @Test
    void basicScan() {
        AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(AutoAppConfig.class);
        MemberService memberService = ac.getBean(MemberService.class);
        assertThat(memberService).isInstanceOf(MemberService.class);
    }
}

 

로그를 보자.

 

∨ ClassPathBeanDefinitionScanner  <- 요런 애가 보이면서

@Component를 붙였던 스캔대상 클래스들이 대상이 되었다.

 

16:44:12.363 [main] DEBUG org.springframework.context.annotation.ClassPathBeanDefinitionScanner - Identified candidate component class: file [C:\Users\kye33\study\core\build\classes\java\main\hello\core\discount\RateDiscountPolicy.class]
16:44:12.366 [main] DEBUG org.springframework.context.annotation.ClassPathBeanDefinitionScanner - Identified candidate component class: file [C:\Users\kye33\study\core\build\classes\java\main\hello\core\member\MemberServiceImpl.class]
16:44:12.368 [main] DEBUG org.springframework.context.annotation.ClassPathBeanDefinitionScanner - Identified candidate component class: file [C:\Users\kye33\study\core\build\classes\java\main\hello\core\member\MemoryMemberRepository.class]
16:44:12.370 [main] DEBUG org.springframework.context.annotation.ClassPathBeanDefinitionScanner - Identified candidate component class: file [C:\Users\kye33\study\core\build\classes\java\main\hello\core\order\OrderServiceImpl.class]

 

 

 그리고 곧.. 오ㅏ우~ 

싱글톤빈으로 객체가 생성되었고 의존관계까지 주입되었다. (autowiring)

 

16:44:12.572 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'autoAppConfig'
16:44:12.580 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'rateDiscountPolicy'
16:44:12.582 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'memberServiceImpl'
16:44:12.616 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'memoryMemberRepository'
16:44:12.617 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Autowiring by type from bean name 'memberServiceImpl' via constructor to bean named 'memoryMemberRepository'
16:44:12.621 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'orderServiceImpl'
16:44:12.625 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Autowiring by type from bean name 'orderServiceImpl' via constructor to bean named 'memoryMemberRepository'
16:44:12.625 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Autowiring by type from bean name 'orderServiceImpl' via constructor to bean named 'rateDiscountPolicy'

 

 

∨ 스프링빈 이름 기본규칙

: 클래스명 & 맨앞글자는 소문자로 바뀜

 

∨ @Autowired

: 자동으로 DI

: 기본 조회전략 - (생성자 파라미터에) 명시된 것과 동일타입인 빈을 DI

cf) getBean(MemberRepository.class)와 동일하다고 이해하자

: 생성자가 딱 1개만 있으면 생략가능

반응형
다른 블로그