• 자동 주입과 함께 사용되는 기능
  • 스프링이 직접 클래스를 검색해서 빈으로 등록해주는 기능
  • 설정 코드가 크게 줄어듦

Component-scan은 xml에 일일이 빈등록을 하지않고 각 빈 클래스에 @Component를 통해 자동 빈 등록이 된다.

@Component @Controller @Service @Repository와 같은 어노테이션을 자동 등록 처리해준다.

 

 

 

@Component 애노테이션으로 스캔 대상 지정

 

 

스프링이 검색해서 빈으로 등록할 수 있으려면 클래스에 @Component 애노테이션을 붙여야 한다.
이 애노테이션은 해당 클래스를 스캔 대상으로 표시한다.

 

  • @Component 애노테이션에 값을 주면 그 값을 빈 이름으로 사용한다.
    ex. @Component("listPrinter")

 

 


@ComponentScan 애노테이션으로 스캔 설정

 

@Component 애노테이션을 붙인 클래스를 스캔해서 스프링 빈으로 등록하려면, 설정 클래스에 @ComponentScan 애노테이션을 적용해야한다.

 

 

 

@Configuration
@ComponentScan(basePackages = {"spring"})
public class AppCtx{
    ...
}

 

 

 

이 코드를 보면 AppCtx 클래스에서

 

@ComponentScan 애노테이션을 사용하여 @Component 애노테이션이 붙은 클래스를 검색해서 빈으로 등록해주기 때문에 설정 코드가 확연히 줄어든다.


또 컴포넌트 스캔 애노테이션을 살펴보면 basePackages 속성값은 {"spring"}이다. 이 속성은 스캔 대상 패키지 목록을 지정하는 것이다.
이는 spring 패키지와 그 하위 패키지에 속한 클래스를 스캔 대상으로 설정한다. 스캔 대상에 해당하는 클래스중 @Component 애노테이션이 붙은 클래스의 객체를 생성해 빈으로 등록한다.

 

 


 

 

스캔 대상에서 제외하거나 포함하기

 

excludeFilters 속성을 사용하면 스캔할 때 특정 대상을 자동 등록 대상에서 제외할 수 있다.

// 정규 표현식을 사용해서 제외 대상을 지정한다.
// "spring."으로 시작하고 Dao로 끝나는 정규 표현식을 지정
@ComponentScan(basePackages = {"spring"},
    excludeFilters = @Filter(type = FilterType.REGEX, pattern = "spring\\..*Dao"))





// AspectJ 패턴을 사용해 대상을 지정한다.
// spring 패키지의 Dao로 끝나는 타입을 지정
// AspectJ 패턴이 동작하려면 의존 대상에 aspectjweaver모듈을 추가해야한다.
@ComponentScan(basePackages = {"spring"},
        excludeFilters = @Filter(type = FilterType.ASPECTJ, pattern = "spring.*Dao"))





// 특정 애노테이션을 붙인 타입을 컴포넌트 대상에서 제외한다.
// 패턴은 Stringp[] 타입이므로 배열을 이용해 패턴을 한 개 이상 지정할 수 있다.
@ComponentScan(basePackages = {"spring", "spring2"},
        excludeFilters = @Filter(type = FilterType.Annotation, pattern = {NoProduct.class, ManualBean.class}))





// 특정 타입이나 그 하위 타입을 컴포넌트 스캔 대상에서 제외한다.
@ComponentScan(basePackages = {"spring"},
        excludeFilters = @Filter(type = FilterType.ASSIGNABLE_TYPE, classes = MemberDao.class))






// 설정할 필터가 2개 이상이면 excludeFilters 속성에 배열을 사용해서 목록을 전달하면 된다.
@ComponentScan(basePackages = {"spring"},
        excludeFilters = {
                @Filter(type = FilterType.ANNOTATION, classes = ManualBean.class),
                @Filter(type = FilterType.REGEX, pattern = "spring2\\..*")
        }

 

 

 

 

 

 

@Component 애노테이션을 붙인 클래스만 스캔 대상에 포함되는 것이 아니다.

  • @Component
  • @Controller
  • @Service
  • @Repository
  • @Aspect
  • @Configuration

@Aspect를 제외하고 나머지 애노테이션은 @Component 애노테이션에 대한 특수 애노테이션이다.




 

컴포넌트 스캔에 따른 충돌 처리


컴포넌트 스캔 기능을 사용해서 Bean을 등록할 경우, 아래와 같은 두 가지 충돌이 발생 가능

  1. Bean 이름의 충돌
  2. 수동 등록에 따른 충돌

2-1. Bean 이름 충돌

  • 서로 다른 패키지에 같은 클래스의 이름이 존재하고, 두 클래스 모두 @Component 어노테이션이 붙게 된다면,
    Exception이 발생하게 됨
  • 이럴 경우, 둘 중 하나에 명시적으로 Bean 이름을 지정해서 이름 충돌을 피해야 함

2-2. 수동 등록에 따른 충돌

  1. 같은 클래스를 같은 이름으로 설정할 때:
    • @Component 어노테이션을 통해 이미 지정한 Bean의 클래스 이름이 존재하지만,
      클래스 설정에 직접 해당 클래스를 동일한 이름으로 정해 등록하는 경우 발생
    • 즉, 스캔할 때 사용하는 Bean 이름과 수동 등록한 이름이 같을 경우, 수동 등록한 Bean이 우선시 됨
  2. 같은 클래스를 다른 이름으로 설정할 때:
    • 만약, 스캔할 때 사용하는 Bean 이름과 동일한 클래스를 다른 이름으로 수동 등록하는 경우에는
      다른 이름의 두 개의 Bean이 만들어지게 됨
    • 이런 경우에는 @Qualifier 어노테이션을 통해 알맞은 Bean을 선택해야 함

 


Reference.

'초보 웹 개발자를 위한 스프링5 프로그래밍 입문' link1

+ Recent posts