안녕하세요 개발자 문문입니다.
오늘은 컴포넌트 스캔에 대해 공부하겠습니다.
컴포넌트 스캔이란 스프링이 직접 클래스를 검색해서 빈으로 등록해주는 기능입니다.
- @Component
- 스프링이 검색해서 빈으로 등록하도록 하려면 @Component 애노테이션을 붙여줘야합니다.
@Component
public class MemberDao {
...
- 이런 경우에는 빈의 이름이 memberDao가 됩니다.
이처럼 이름을 명시하지 않으면 클래스명의 앞글자를 소문자로 변경하여 빈 이름으로 설정합니다.
@Component("infoPrinter")
public class MemberInfoPrinter {
...
- 이름을 명시해주었다면, infoPrinter가 빈의 이름으로 설정됩니다.
이처럼 @Component안에 이름을 명시해준다면 명시해준 이름으로 해당 클래스 빈의 이름이 됩니다.
- @ComponentScan
- @ComponentScan은 @Component 애노테이션을 붙인 클래스를 스캔해서 스프링 빈으로 등록해줍니다.
@Configuration
@ComponentScan(basePackages = {"spring"})
public class AppCtx {
...
- basePakages에는 스캔 대상 패키지 목록을 의미합니다.
- 예제에서는 spring과 그 하위 패키지에 속한 클래스중 @Component가 붙어있는 클래스를 빈으로 등록합니다.
- excludeFilters 속성
- excludeFilters 속성을 사용하면 스캔할 때 특정 대상을 자동 등록 대상에서 제외합니다.
@Configuration
@ComponentScan(basePackages = {"spring"}, excludeFilters = @Filter(type = FilterType.REGEX, pattern = "spring\\..*Dao"))
public class AppCtxWithExclude {
...
- type = FulterType.REGEX : 정규 표현식을 사용해서 제외 대상 지정
- pattern = FilterType에 적용할 값 지정(패키기 spring 하위에 Dao로 끝나는 클래스)
@Configuration
@ComponentScan(basePackages = {"spring"}, excludeFilters = @Filter(type = FilterType.ASPECTJ, pattern = "spring.*Dao"))
public class AppCtxWithExclude {
...
- type = FilterType.ASPECTJ : 정규식 표현식 대신에 AspectJ 패턴을 사용해서 대상 지정
- pattern = spring 패키지의 Dao로 끝나는 타입 지정
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface NoProduct {
}
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface ManualBean {
}
- @Retention : 이 애노테이션은 실행 중(Run-Time)에 JVM이 읽고 사용
- @Target : 클래스, 인터페이스, enum, 애노테이션 등에만 사용
- @interface : 커스텀 애노테이션을 정의
@ManualBean
@Component
public class MemberDao {
...
@Configuration
@ComponentScan(basePackages = {"spring"}, excludeFilters = @Filter(type = FilterType.ANNOTATION, classes = {NoProduct.class, ManualBean.class}))
public class AppCtxWithExclude {
...
- type = FilterType.ASPECTJ : classes에 명시된 애노테이션(@NoProduct, @ManualBean)이 붙어있는 클래스는 컴포넌트 스캔 대상에서 제외합니다.
@Configuration
@ComponentScan(basePackages = {"spring"}, excludeFilters = @Filter(type = FilterType.ASSIGNABLE_TYPE, classes = MemberDao.class))
public class AppCtxWithExclude {
...
- type = FilterType.ASSIGNABLE_TYPE : 특정 타입, 하위 타입을 컴포넌트 대상에서 제외합니다.
@Configuration
@ComponentScan(basePackages = {"spring"},
excludeFilters = {
@Filter(type = FilterType.ANNOTATION, classes = ManualBean.class),
@Filter(type = FilterType.REGEX, pattern = "spring2\\..*")
})
public class AppCtxWithExclude {
...
- 설정할 필터가 두 개 이상이면 배열을 사용합니다.
- 기본 스캔 대상
- @Component 애노테이션을 붙인 클래스만 컴포넌트 스캔 대상에 포함되는건 아닙니다.
- 다음 애노테이션을 붙인 클래스는 컴포넌트 스캔 대상에 포함됩니다.
- @Component
- @Controller
- @Service
- @Repository
- @Aspect
- @Configuration
- 컴포넌트 스캔에 따른 충돌처리
1. 서로 다른 두 패키지에 이름이 같은 클래스가 존재하고 모두 @Component가 붙어있다면 충돌이 발생합니다.
- 이런 경우에는 둘 중 하나에 명시적으로 빈 이름을 지정해야합니다.
2. @Component로 등록한 빈과 @Bean으로 수동 등록한 빈의 이름이 같을 경우
- 이런 경우에는 수동 등록한 빈이 우선으로 등록됩니다.
'Spring 개념정리' 카테고리의 다른 글
[Spring] MVC : 요청 매핑, 커맨드 객체, 리다이렉트, 모델 (2) | 2025.07.06 |
---|---|
[Spring] 스프링 MVC 프레임워크 동작 방식 (0) | 2025.07.02 |
[Spring] AOP(Aspect Oriented Programming) (0) | 2025.07.01 |
[Spring] 빈 라이프사이클과 범위 (2) | 2025.06.30 |
[Spring] 스프링 DI(Dependency Injection) (1) | 2025.06.24 |