Spring

TIL-2 컴포넌트 스캔과 의존 관계 자동 주입 DI

다오__ 2023. 5. 16. 18:00

스프링 빈을 등록할 대는 자바 코드 @Bean, XML <bean>등을 통해 직접 스프링 빈을 나열했다.

 

하지만 수십 수백개가 되면 일일히 등록하기도 귀찮고 누락위험이 있다.

그래서 설정 정보가 따로 없어도 자동으로 스프링 빈을 등록하는 컴포넌트 스캔이라는 기능을 제공한다.

의존관계도 자동으로 주입하는 @Autowired라는 기능도 제공한다.

 

컴포넌트 스캔은 @Component 어노테이션이 붙은 클래스를 찾아 자동으로 스프링 빈으로 등록해준다.

  • (excludeFilters : 자동으로 스프링빈으로 등록되는 중에 제외 시킬 정한다.)

 

(여기에선 Configuration 클래스를 제외하도록 설정했다.)

AppConfig.class 설정 파일이기 때문에 컴포넌트 어노테이션 충돌이 일어나기 때문에 제외하였다.

 

구현체들에 전부 @Component 붙여주자

생성자에는 @Autowired를 붙여주자

 

@Autowired

자동으로 의존관계를 주입해준다.

해당 타입에 맞는 빈을 찾아서 의존관계주입을 해준다.

 

이전에 작성한 AppConfig.class에서는 @Bean으로 직접 설정 정보를 작성했고, 의존관계도 직접 명시했다.

하지만 이런 설정정보자체가 이젠 없기에 의존관계주입도 클래스 안에서 해결해야 한다.

 

 

결과

테스트코드 작성

 

로그로도 확인

 

 

컴포넌트 스캔의 작동원리

 

 

 

 

 

 

탐색 위치와 기본 대상, 필터

 

탐색 위치와 기본 스캔 대상

모든 자바 클래스를 전부 컴포넌트 스캔하면 오랜 시간이 걸리기 때문에 필요한 위치부터 탐색하도록 시작 위치를 정할 있다.

 

이미지를 보면, hello.core.member 이하의 패키지만 탐색할 수 있는 걸 볼 수 있다. 또한 로그를 보면 member패키지에 관련된 것들만 싱글톤으로 생성된것을 있다.

 

basePackages = 기본 경로 설정

basePackageClasses = 클래스 단위로 설정

 

따로 경로를 지정하지 않으면 컴포넌트 스캔 어노테이션을 지정한 클래스의 패키지 경로(여기선 hello.core) 부터 탐색을 시작한다.

 

따라서

패키지 위치를 지정하지 않고, 설정정보 클래스의 위치를 프로젝트 최상단에 놓는 것을 권장한다.

 

 

 

 

필터

직접 정의한 어노테이션을 테스트 해보며 알아보자.

 

 

 

beanA MyIncludeComponent 어노테이션을 사용해 스캔이 되었지만, beanB MyExcludeComponent 어노테이션을 사용해 NoSuchBeanDefinitionException 발생하였다.

 

스프링 부트는 컴포넌트 스캔을 기본으로 제공하는데, 옵션을 변경하면서 쓰기 보다는 스프링의 기본 설정에 최대한 맞추어 사용하는 것을 권장하고, 선호한다.

 

 

 

중복 등록과 충돌

컴포넌트 스캔에서 같은 이름을 등록하는 가지 상황이 있다.

 

1.  자동 등록 vs 자동 등록

컴포넌트 스캔에 의해 자동으로 스프링 빈이 등록되는데, 이름이 같은 경우 스프링은 예외를 발생시킨다(ConflictingBeanDefinitionException)

 

 

2.  수동 등록 vs 수동 등록

 

의도적으로 이름을 같게 하여 테스트 해보았다.

 

충돌이 일어나는 것을 확인 있다

 

 

3.수동 등록 vs 자동 등록

테스트에 성공하게 되는데 그 이유는 로그를 보면 된다. 오버라이딩이 되었다는 것을 확인 있다.

수동 빈이 우선권을 가지며, 자동 빈을 오버라이딩 해버린다.

 

하지만 이런결과는 개발의도와 다르게 설정이 꼬여서 만들어지는 경우가 대부분이다.

그래서 최근 스프링 부트에서는 수동 등록과 자동 빈등록이 충돌나면 오류가 발생하도록 기본 값을 바꾸었다.

스프링부트로 실행 에러메시지 :