포스트

10. 컴포넌트 스캔와 의존관계 자동 주입

10. 컴포넌트 스캔와 의존관계 자동 주입

컴포넌트 스캔와 의존관계 자동 주입

  • 스프링 빈은 @Bean이나 xml을 통해 생성하였다.
  • 하지만 Bean이 엄청 많아진다면…?
  • 스프링 내에는 설정 정보 없이도 자동으로 스프링 빈은 등록하는 컴포넌트 스캔이라는 기능을 제공
  • 의존관계까지 자동으로 주입하는 @AutoWired 라는 기능도 제공한다.

일반적인 컴포넌트 스캔은 모든 @Configuration 이 붙은 설정도 자동 등록이 되기에 필터를 활용해 제외할 것을 적어준다. (@Configuraion 안에 @Component 가 존재한다…)

1
2
3
4
5
6
7
8
9
AutoAppConfig.java

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

  • @ConmponentScan : 모든 @Component 어노테이션이 붙은 클래스를 스캔에 스프링 빈에 등록한다.
  • 그렇다면 의존관계의 주입은?
    • @Autowired 를 사용해서 의존관계를 주입한다!
    1
    2
    3
    4
    5
    6
    7
    8
    9
    
      @Component
      public class MemberServiceImpl implements MemberService{
        
      	private final MemberRepository memberRepository;
        
      	@Autowired
      	public MemberServiceImpl(MemberRepository memberRepository) {
      		this.memberRepository = memberRepository;
      	}
    
    • 자동으로 @Compoent 를 찾아서 @Autowored 를 통해 의존관계 자동으로 주입한다.
    • 단 주입받는 객체 또한 @Component 여야한다.

어떻게 컴포넌트 스캔과 자동 주입이 이뤄지는가?

Untitled

  • @Component 가 붙은 모든 클래스를 스프링 빈으로 등록한다.
  • 빈의 기본 이름은 클래스명과 동일하지만 앞글자를 소문자로 사용한다.
    • MemberServiceImplmemberServiceImpl
    • 임의의로 지정하고 싶으면 @Component( ) 로 한다.

AutoWired는 어떻게 이뤄지는건가?

Untitled

  • 생성자에 @Autowired 를 지정하면 컨테이너가 알아서 빈을 주입한다.
  • 기본적으론 타입이 같은 빈을 찾아서 주입
    • getBean(클래스이름.class) 와 같다.
  • 생성자 파라미터가 많아도 알아서 전부 bean 찾아서 주입해준다.

탐색 위치와 기본 스캔 대상

  • 모든 클래스를 탐색하기엔 조금 시작이 된다.

    1
    2
    3
    
       import "내패키지경로.디폴트경로이다."
          
        basePackages = "hello.core.탐색할패키지경로"
    
    • 이외의 패키지는 스캔 하지 않는다.
    • 오직 저기부터 하위만 한다.
    • 만약 지정하지 않으면 스캔 하는 패키지의 하위부터 시작한다.

일반적으로 패키지 위치를 지정하지 않고 시작 루트에 AppConfig 같은 메인 설정 정보를 두고 @ComponentScan 어노테이션을 통해 지정을 생략한다.

컴포넌트 스캔 대상

단순히 @Component 만 사용하지 않고 다양한 어노테이션으로 사용이 가능한다.

  • @Component : 컴포넌트 스캔
  • @Service : 컨트롤러
    • 딱히 뭘 하진 않지만 개발자가 인지용
  • @Controller : 비즈니스 로직
    • MVC의 컨트롤러로 인식
  • @Repository : 데이터 접근 계층
    • 스프링 데이터 접근 계층으로 인식, 데이터 계층의 예외를 스프링 예외로 변환
  • @Configuration : 스프링 설정 정보
    • 스프링 설정보로 인식, 싱글톤 유지를 위한 추가 처리

참고 : 어노테이션에는 상속관계가 없다. 즉 이건 Java의 지원 기능이 아닌 스프링이 지원하는 것이다.

컴포넌트 충돌

  • 컴포넌트 스캔에 있어 같은 이름의 빈이 충돌난다면?

@Component(name = "수동이름 지정") 로 같은 이름

  • 당연하게 충돌 난다…

@Component(name = "수동이름 지정") vs @Component

  • 후자가 자동이라면?
  • 수동으로 이름 지은게 자동 이름과 같다면?
  • 충돌이 일어나지 않는다..?
    • 수동 빈이 우선권을 가지고 오버라이딩 한다.

이러한 결과는 추후 잡기 힘든 버그를 유발한다…

  • 그렇기에 수동 빈등록 vs 자동 빈등록 이슈가 발생시 스프링 부트가 에러를 생성해준다
  • 언제나 어설픈 추상화는 사용하지 않은게 좋다.
이 기사는 저작권자의 CC BY 4.0 라이센스를 따릅니다.

© 김규형. 일부 권리 보유

Powered by Jekyll with Chirpy theme