Component scan

  • 자동 주입과 함께 사용하는 추가 기능이 component scan이다.
  • 스프링이 직접 클래스를 검색해서 bean으로 등록해주는 기능이다.
  • bean 설정에 등록하지 않아도 원하는 클래스를 bean으로 등록할 수 있어 component scan을 사용하면 bean 설정 코드가 많이 줄어든다.

컴포넌트 스캔의 등록

1) @Component 으로 스캔 대상 지정

  • 서비스 코드에 붙인다
@Component
public class MemberDao {
//..
}

이렇게 되면 bean이름은 "memberDao"로 자동지정된다. 자동 지정 규칙은 camelCase다.

  • 아래와 같이 속성을 줄 수 있다
@Component("memberRepository")
public class MemberDao {
//..
}

속성을 지정하면 해당 이름으로 변경된다.

2) @ComponentScan 으로 스캔 설정

  • bean 설정 코드에 아래와 같이 추가한다
@Configuration
@ComponentScan(basePackages = {"student"}) // <<< sudent패키지 하위의 클래스를 스캔 대상으로 한다.
public class AppContext {
    //...
}
  • 컴포넌트로 등록하면 bean설정 코드가 많이 줄어든다.

3) getBean()의 변경

  • 컴포넌트로 bean 생성을 지정하게 되면 camelCase 이름을 가진다.
  • 컴포넌트 스캔을 사용하고자 한다면, 기존의 getBean 메소드에서 bean 객체를 불러올때 설정한 닉네임을 없애거나 컴포넌트 속성의 값으로 맞춰야 한다.
// before (아무 속성을 주지 않았을때)
    MemberRegisterService regSvc = 
                ctx.getBean("memberRegSvc", MemberRegisterService.class);
//after
MemberRegisterService regSvc = 
                ctx.getBean(MemberRegisterService.class);

스캔 대상의 필터링 (포함하기, 제외하기)

1) @ComponentScan(excludeFilters)

  • 특정 bean 객체를 자동 등록 대상에서 제외할 수 있다.

a. 정규식 패턴

@Configuration
@ComponentScan(basePackages = {"spring", "spring2" }, 
    excludeFilters = { 
            @Filter(type = FilterType.REGEX, pattern = "spring\\..*Dao")            
})
public class AppCtxWithExclude {
    //..
  • 정규표현식으로 패턴으로 컴포넌트 스캔 대상을 필터링 한다.
  • 위의 패턴은 spring. 으로 시작하고 Dao로 끝나는 클래스를 필터링 한다.

b. AspectJ 패턴

@Configuration
@ComponentScan(basePackages = {"spring", "spring2" }, 
    excludeFilters = { 
            @Filter(type = FilterType.ASPECTJ, pattern = "spring.*Dao")         
})
public class AppCtxWithExclude {
  • AspectJ 패턴은 정규식과 약간 다르다.
  • pattern은 String[] 타입이라 한개 이상 지정할 수 있다
  • 작동하려면 maven에 AspectJ를 추가해야한다.
<dependency>
    <groupId>org.aspectj</groupId>
    <artifactId>aspectjweaver</artifactId>
    <version>1.8.13</version>
</dependency>

c. 어노테이션 패턴

  • 특정 어노테이션을 붙이면 제외되도록 할 수 있다.
  • 먼저 아래와 같이 어노테이션을 만든다.
//ManualBean.class
@Retention(RUNTIME)
@Target(TYPE)
public @interface ManualBean {

}
  • 그 다음 컴포넌트 스캔 설정의 필터에 아래와 같이 추가하면 된다.
  • 여러개의 어노테이션 등록도 가능하다 {class1,class2}
@Configuration
@ComponentScan(basePackages = {"spring", "spring2" }, 
    excludeFilters = { 
            @Filter(type = FilterType.ANNOTATION, classes = ManualBean.class )          
})
public class AppCtxWithExclude {
    //...

d. Assignable_type 패턴

@Configuration
@ComponentScan(basePackages = {"spring", "spring2" }, 
    excludeFilters = { 
            @Filter(type = FilterType.ASSIGNABLE_TYPE, classes = MemberDao.class )          
})
public class AppCtxWithExclude {
    //...
  • 위와 같이 클래스 자체를 지정해서 제외할 수도 있다.

기본 스캔 대상

  • 스프링에서 @Component 이외에 스캔대상으로 자동 편입하는 어노테이션이 몇가지 더 있다
  1. @Component
  2. @Controller
  3. @Service
  4. @Repository
  5. @Aspect
  6. @Configuration

컴포넌트 충돌 T/S

1) bean 이름 충돌

  • 컴포넌트 스캔을 여러개 하는 경우 같은 클래스를 등록하려는 경우가 있는데 이럴때는 명시적으로 이름을 등록해야한다 getBean()

2) 수동 등록한 bean과 충돌

  • bean 등록시 수동으로 명시한 bean을 우선순위로 등록한다.
  • 같은 객체를 바라보는 경우는 @Qualifier로 알맞은 bean을 선택해야 한다.

Comments