프로그래밍 끄적끄적
[SpringBoot] 컴포넌트 스캔과 자동 주입 본문
🌳 컴포넌트 스캔 (@ComponentScan)
컴포넌트 스캔은 @Component 와 @Service, @Repository, @Controller 어노테이션이 설정된 클래스들을 자동으로 스캔하여 스프링 빈으로 등록해준다.
이때 이를 설정하는 파일인 @Configuration도 등록 대상이 되는데, 이때 테스트를 위해 만들었던, 그리고 실습을 위해 작성했던 다른 @Configuration 클래스들도 모두 등록될 수 있기 때문에 excludeFilters 설정을 이용하여 제외해준다. (Config 파일들은 AnnotationConfigApplicationContext 객체를 통해 개발자가 직접 코드에 삽입하기 때문에 자동 등록하지 않아도 문제가 생기지 않는다.) --> 일반적으로는 이렇게 해 줄 필요 없다.
🍃 관련된 설정들
▪ includeFilters: 조건을 만족하는 클래스만 스캔한다.
▪ excludeFilters: 조건을 만족하는 클래스는 제외하고 스캔한다.
▪ basePackages: 탐색할 위치를 지정한다. (지정한 패키지를 포함한 하위 파일들에 대해서만 탐색함)
- 이를 지정하지 않으면 현재 클래스의 패키지가 기준이 된다. (Config 파일이 최상단에 존재해야 하는 이유)
▪ basePackageClasses: 지정한 클래스의 패키지가 탐색할 위치가 된다.
컴포넌트 스캔을 위해 Service와 Repository 레이어에 있는 실제 필요한 구현체 클래스들에게 @Component 또는 @Service, @Repository 어노테이션을 추가하고 자동 주입을 위한 부분(생성자 또는 Setter)에 @Autowired 어노테이션을 붙여준다. 이러면 필요한 빈을 조회하여 연결해준다.
이때 스프링 빈에 등록되는 이름은 해당 클래스의 앞글자만 소문자로 바뀌어 자동으로 저장된다. 명시적으로 이름을 지정하기 위해선 @Component("[빈 이름]")이라고 작성한다. (스프링 빈 이름은 고유해야 한다!)
🌳 컴포넌트 스캔 문제점 및 주의점
컴포넌트 스캔은 @Bean으로 직접 등록할 필요도 없고 의존관계도 코드로 작성할 필요가 없다. 대신, 의존관계 주입도 해당 클래스 안에서 해결해야 한다. 즉, 하나하나 각각 파일에 들어가서 필요한 부분에 어노테이션을 붙여주어야 하기 때문에 가독성이 떨어진다.
@Autowired를 통한 의존관계 주입은 디폴트로 getBean([타입])으로만 조회하기 때문에 해당 타입에 대해 오직 하나의 빈만 존재해야 한다. (0개여도 Exception이 발생하고, 2개 이상이어도 Exception이 발생함) 따라서 주의할 점은 "실제로 사용될 객체"에 대해서만 @Component 어노테이션을 붙여주어야 한다는 것이다. 예를 들어 DiscountPolicy의 구현체 클래스들인 FixDiscountPolicy와 RateDiscountPolicy 클래스 모두 @Component 어노테이션을 붙인다면 충돌로 인해 오류가 발생한다.
🌳 컴포넌트 스캔 기본 대상
기본적으로 @Component 어노테이션이 붙은 클래스들은 스캔 대상이 된다.
이때 @Controller, @Service, @Repository, @Configuration도 내부에 @Component가 포함되어 있기 때문에 스캔 대상에 포함된다.
🌳 수동 빈 등록 VS 자동 빈 등록
@Bean 어노테이션을 통해 수동으로 beanA라는 빈을 등록하고, @ComponentScan에 의해 자동으로 beanA라는 빈이 등록되었을 경우 수동으로 등록된 빈이 우선권을 가진다. (빈 이름이 같지만, 우선순위가 존재하기 때문에 오버라이딩 되므로 오류가 발생하지 않는다.)
하지만... 개발자도 모르게 저질렀던 실수가 정상적으로 잘 작동하는 것처럼 보인다면,, 버그를 잡기 훨씬 더 어려워지지 않을까?
따라서 최근 스프링 부트에서 수동 빈 등록과 자동 빈 등록이 충돌나면 아래와 같은 오류 로그를 발생한다.
Overriding bean definition for bean 'memoryMemberRepository' with a different definition: replacing
🌟 스프링 어노테이션들의 부가 기능
▪ @Controller: 스프링 MVC 컨트롤러로 인식한다.
▪ @Repository: 스프링 데이터 접근 계층으로 인식한다, 데이터 계층의 예외를 스프링 예외로 변환해준다.
▪ @Configuration: 스프링 설정 정보로 인식한다, 스프링 빈이 싱글톤을 유지할 수 있도록 해준다.'
▪ @Service: 비즈니스 계층을 인식하는데 도움이 된다.(별다른 부가기능 제공하지 않음)
'백엔드 > 스프링' 카테고리의 다른 글
[SpringBoot] 의존관계 주입 (0) | 2021.09.07 |
---|---|
[SpringBoot] 컴포넌트 스캔 필터링 (0) | 2021.09.03 |
[SpringBoot] 싱글톤 (0) | 2021.09.01 |
[SpringBoot] BeanDefinition (0) | 2021.09.01 |
[SpringBoot] 스프링 컨테이너 (0) | 2021.09.01 |