Spring 개념정리

[Spring] 컴포넌트 스캔

개발자 문문 2025. 6. 30. 21:50

안녕하세요 개발자 문문입니다.

오늘은 컴포넌트 스캔에 대해 공부하겠습니다.

 

컴포넌트 스캔이란 스프링이 직접 클래스를 검색해서 빈으로 등록해주는 기능입니다.

 

  • @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으로 수동 등록한 빈의 이름이 같을 경우

- 이런 경우에는 수동 등록한 빈이 우선으로 등록됩니다.