일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
- @Component
- Nodejs
- AWS
- Spring
- 컴포넌트스캔
- nestJS
- 가상면접사례로배우는대규모시스템설계기초
- thymeleaf
- nestjs auth
- @Autowired
- 알고리즘
- 파이썬
- 코딩테스트
- 카카오 코테
- nestjs typeorm
- 카카오
- git
- spring boot
- C언어
- 프로그래머스
- 해시
- 시스템호출
- TypeORM
- OpenCV
- 코테
- 구조체배열
- 스프링
- 카카오 알고리즘
- C++
- python
- Today
- Total
공부 기록장 💻
[Spring] 컴포넌트 스캔의 탐색 위치와 기본 탐색 대상, 커스텀 애노테이션으로 필터 옵션 지정하기 (basePackages, includeFilters, excludeFilters, @ComponentScan) 본문
[Spring] 컴포넌트 스캔의 탐색 위치와 기본 탐색 대상, 커스텀 애노테이션으로 필터 옵션 지정하기 (basePackages, includeFilters, excludeFilters, @ComponentScan)
dream_for 2023. 2. 2. 11:29
지난번 AutoAppConfig의 @ComponentScan을 이용하여 스프링 컨테이너가 자동적으로 @Component 애노테이션이 추가되어 있는 컴포넌트들을 스프링 빈으로 등록하고, @Autowired를 통해 의존 관계를 자동으로 주입하는 컴포넌트 스캔 기능을 사용하였다.
이번에는 컴포넌트 스캔의 기본 탐색 위치와, 직접 지정을 통한 스캔 대상에 대해 학습해보자.
컴포넌트 스캔의 탐색 위치
모든 자바 클래스를 전부 다 컴포넌트 스캔하면 시간이 오래 걸리기 때문에, 꼭 필요한 위치부터 탐색하도록 시작 위치를 지정할 수 있다.
기본 스캔 대상
아래와 같이 지정하지 않는 경우는, 디폴트 값으로 @ComponentScan이 붙은 설정 정보 클래스 패키지가 시작 위치가 된다.
현재 AutoAppConfig의 위치는 다음과 같이 hello.core 패키지 바로 아래에 존재하고 있으므로, hello.core 내의 모든 자바 파일이 컴포넌트 스캔 대상 파일이 되는 것이다,
탐색할 패키지의 시작 위치 직접 지정
basePackages 를 이용하면, 해당 패키지를 포함한 하위 패키지를 모두 탐색하게 된다.
아래와 같이 basePackages = "hello.core.member" 또는 basePackages = {"hello.core.member", "hello.core.order"} 와 같이 여러 시작 위치를 지정할 수 있다.
basePackageClasses 를 이용해 지정한 클래스의 패키지를 탐색 시작 위치로 지정할 수 도 있다.
권장하는 방법과 관례
패키지 위치를 지정하지 않고, 설정 정보 클래스의 위치를 프로젝트의 최상단에 두는 방법이 많이 쓰인다.
즉, basePackages 지정은 생략하고 @ComponentScan 애노테이션이 붙은 설정 정보 클래스를 프로젝트의 시작 루트에 두는 것이다.
Spring Boot의 경우, 대표 시작 정보인 @SpringBootApplication을 프로젝트 시작 루트 위치에 두는 것이 관례이다. (기보적으로 @ComponentScan을 포함하고 있다.)
컴포넌트 스캔의 기본 대상
컴포넌트 스캔은 @Component 뿐만 아니라 아래의 요소들 또한 추가로 스프링 빈 등록 대상에 포함한다.
(컴포넌트 스캔의 용도 뿐 아니라 스프링은 부가 기능을 수행하기도 한다.)
- @Component - 컴포넌트 스캔에서 사용
- @Controller - 스프링 MVC 컨트롤러로 인식
- @Service - 스프링의 중요한 핵심 비즈니스 로직에서 사용, 비즈니스 계층임을 인식하도록 도움을 주는 역할 (특별한 처리를 하지는 않는다.)
- @Repository - JPA, JDBC 등의 스프링 데이터 접근 계층으로 인식하며, 데이터 계층의 예외를 추상화된 스프링 예외로 변환해준다.
- @Configuration - 스프링 설정 정보로 인식하며, 스프링 빈이 싱글톤을 유지하도록 추가 처리를 함
컴포넌트 스캔의 필터
이전 글에서 @ComponentScan을 이용한 자동 컴포넌트 스캔 기능에 대해 배웠다. 이를 위해 기존에 @Bean 을 추가하여 스프링 빈을 직접 등록하고, 의존 관계를 직접 주입하여 설정 정보를 구성한 AppConfig가 아닌, AutoAppConfig를 사용하기 위해 @ComponentScan에 excludeFilters 필터 옵션을 지정하였다. 따라서 기존에 @Configuration이 붙은 설정 정보 파일의 컴포넌트들은 스프링 빈 등록 대상에서 제외되었다.
따라서 위의 예시와 같이, 우리는 아래 필터 옵션을 이용해 특정 컴포넌트 대상을 추가적으로 지정하거나 제외를 시킬 수 있다.
- includeFilters : 컴포넌트 스캔 대상을 추가적으로 지정
- excludeFilters : 컴포넌트 스캔에서 제외할 대상을 지정
커스텀 애노테이션 생성 및 스프링 빈 지정과 제외 (includeFilters, excludeFilters 옵션)
@Component의 역할을 하는 두 커스텀 어노테이션을 만들어, 특정 컴포넌트(BeanA)는 includeFilters 옵션을 통해 스프링 빈 등록 대상으로 만들고, 특정 컴포넌트(BeanB)는 excludeFilters 옵션을 통해 스프링 빈 등록 제외 대상으로 만들어보자.
테스트 패키지 내에 다음과 같이 scan > filter 폴더 내에 다음과 같이 생성해보자.
- 컴포넌트 스캔 대상으로 만들 BeanA와 BeanB 클래스
- @Component와 동일한 역할을 하는 커스텀 어노테이션 인터페이스인 MyExcludeComponent, MyIncludeComponent
- 필터옵션을 지정하여 컴포넌트 스캔 테스트를 진행할 ComponentFilterAppConfigTest 클래스
@MyIncludeComponent, @MyExcludeComponent 커스텀 어노테이션 생성
두 커스텀 어노테이션을 각각 다음과 같이 만들자.
위에 지정해주는 4개의 어노테이션은 모두 아래 @Component 어노테이션이 포함하고 있는 메타데이터들 정보를 그대로 추가해준 것이라 할 수 있다. 따라서 두 어노테이션이 모두 @Component의 역할과 동일한 역할을 하도록 만들기 위해 추가해주도록 하자.
BeanA, BeanB 클래스
이제 스프링 빈 등록 대상으로 설정할 BeanA 컴포넌트에는 @MyIncludeComponent 를 적용하고,
스프링 빈 등록의 제외 대상으로 설정할 BeanB 컴포넌트에는 @MyExcludeComponent를 적용하자.
ComponentFilterAppConfig 클래스와 ComponentFilterAppConfigTest 테스트
이제 아래 static class로 ComponentFilterAppConfig 설정 정보 클래스를 만들자.
@ComponentScan의 옵션으로 위에서 만든 MyInlcludeComponent와 MyExcludeComponent 클래스 정보를 각각 includeFilters, ExcludeFilters 의 대상 클래스 지정해주도록 한다.
filterScan() 테스트 코드를 통해, 스프링 컨테이로부터 getBean() 메서드를 통해 빈을 조회하였을 때, beanB는 스프링 빈으로 등록되어 있지 않아 NoSuchBeanDefinitionException 오류를 발생시키는 것을 확인할 수 있다.
FilterType의 옵션
FilterType에는 5가지 옵션이 있다.
- ANNOTATION : 기본값, 애노테이션을 인식하여 동작함
- ASSIGNABLE_TYPE : 지정한 타입과 자식 타입을 인식하여 동작
- ASPECTJ : AspectJ 패턴 사용
- REGEX : 정규 표현식
- CUSTOM : TypeFilter 이라는 인터페이스를 구현해서 처리
특정 컴포넌트를 빈 등록 대상에서 제외시키고 싶은 경우, 다음과 같이 ASSIGNABLE_TYPE 을 사용할 수 있다.
BeanA를 제외시켜보자.
@Component 어노테이션으로도 충분히 스프링 컨테이너에 스프링 빈 등록 대상임을 알릴 수 있으므로, includeFilters을 사용할 일은 거의 없다. 간혹가다 excludeFilters를 사용할 수 있다는 것만 알아두면 된다. (그리고 Spring Boot는 기본적으로 Component Scan을 제공하므로, 옵션을 변경하기보다 스프링의 기본 설정에 최대한 맞추어 사용하는 것이 권장된다.)
'# Tech Studies > Java Spring • Boot' 카테고리의 다른 글
[Spring] 의존 관계 자동 주입의 4가지 방법과 특징, 생성자를 통해 주입해야하는 이유 (0) | 2023.02.03 |
---|---|
[Spring] 컴포넌트 스캔의 중복 등록과 충돌 (수동 빈 등록의 우선권과 오버라이딩 에러) (0) | 2023.02.02 |
[Spring] 컴포넌트 스캔과 의존관계 자동 주입 (@ComponentScan, @Autowired) (0) | 2023.02.02 |
[Spring] 스프링의 싱글톤 컨테이너 (싱글톤 패턴의 필요성과 문제점과 주의점, @Configuration) (0) | 2023.01.27 |
[Spring] 스프링으로의 전환, 스프링 컨테이너 생성과 스프링 빈 등록 과정 (@ApplicationContext, @Configuration, @Bean) (0) | 2023.01.26 |