본문 바로가기

FrameWork/Spring 3.0

[Spring 3.0] CH04-2.어노테이션 기반 빈 객체 스캔

Spring 2.5 부터 @Component 어노테이션, @Service 어노테이션, @Controller 어노테이션이 새롭게 추가 되었다.

1. 어노테이션을 이용한 자동 스캔


@Component("homeController")
public class HomeController {
.......
}

@Componenet 어노테이션을 클래스에 적용 했다면,
<context:component-scan> 태그를 이용해서 스프링이 클래스를 검색할 패키지를 지정하면 된다.

=> @Component 어노테이션이 적용된 클래스를 검색하여 빈으로 등록하게 된다.

#ApplicationContext.xml


<beans xmlns="http://www.springframework.org/schema/beans"
 xmlns:p="http://www.springframework.org/schema/p" xmlns:context="http://www.springframework.org/schema/context"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="http://www.springframework.org/schema/beans  
       http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
       http://www.springframework.org/schema/context
       http://www.springframework.org/schema/context/spring-context-3.0.xsd">

<context:component-scan base-package="madvirus.spring.chap04" scoped-proxy="no">
  <context:include-filter type="regex" expression="kame\.spring\.chap04\.work\.*"/>
  <context:include-filter type="regex" expression="kame\.spring\.chap04\.homecontrol\.*"/>
 </context:component-scan>

</bneas>
 


<context:component-scan> 태그는 어노테이션과 관련해서 아래의 BeanPostProcessor  를 함께 등록해준다.

- RequiredAnnotationBeanPostProcessor
- QutowiredAnnotationBeanPostProcessor
- CommonAnnotationBeanPostProcessor
- ConfigurationClassPostProcessor

따라서, <context:component-scan> 태그를 사용하면
@Component 어노테이션 뿐만 아니라 @Required , @Autowired 과 같은 어노테이션이 함께 적용 된다.



2. 자동 검색된 빈의 이름과 범위

스프링은 기본적으로 검색된 클래스를 빈으로 등록 학 때 클래스의 (첫글자를 소문자로 바꾼) 이름을 빈의 이름으로 사용한다.

#HomeController.java

@Component
public class HomeController {
.......
}


예를들어 위의 클래스의 자동으로 등록되는 빈(bean) 의 이름은 "homeConroller" 가 된다.
이름을 변경하고 싶을때엔 아래와 같이 빈(bean) 의 이름을 명시해 주면 된다.

#HomeController.java

@Component("homeControl")
public class HomeController {
.......
}

스프링은 기본적으로 빈의 범위를 "singleton" 으로 설정한다.
"singleton" 이 아닌 다른범위를 지정하고 싶다면 @Scope 어노테이션을 이용하여 범위를 지정한다.

#Worker.java
import org.springframework.context.annotation.Scope;
import org.springframework.context.annotation.ScopedProxyMode;
import org.springframework.stereotype.Component;

@Component
@Scope(value="prototype", proxyMode=ScopedProxyMode.TARGET_CLASS)
public class Worker {

 public void work(WorkUnit unit) {
  System.out.println(toString() + " work " + unit);
 }

}


ScopedProxyMode 에 정의된 열거값

* NO - 프록시를 생성하지 않음
* INTERFACES - 인터페이스에 대한 프록시를 생성한다
(JDK 다이나믹 프록시를이용해서 프록시 생성)
* TARGET_CLASS - 클래스에 대해 프록시를 생성 (CGLIB 이용)
* DEFAULT - 기본값.
별도의 설정을 하지 않았다면, NO 와 동일하다.
<context:component-scan> 태그에서 설정을 변경 할 수 있다 (Spring 3.0)

#ApplicationContext.xml
<context:component-scan base-package="패키지명" scoped-proxy="no" >

여기서 scoped-proxy 속성에 올 수 있는 값을 "no", "interfaces", "targetClass" 이다.



3. 스캔 대상 클래스 범위 지정하기

<context:include-filter> 태그와 <context:exclude-filter> 태그를 사용하면
자동스캔 대상에 포함시킬 클래스와 포함시키지 않을 클래스를 구체적으로 명시할 수 있다.

#ApplicationContext.xml

<beans xmlns="http://www.springframework.org/schema/beans"
 xmlns:p="http://www.springframework.org/schema/p" xmlns:context="http://www.springframework.org/schema/context"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="http://www.springframework.org/schema/beans  
       http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
       http://www.springframework.org/schema/context
       http://www.springframework.org/schema/context/spring-context-3.0.xsd">

 <context:component-scan base-package="madvirus.spring.chap04" scoped-proxy="no">
  <context:include-filter type="regex" expression="*HibernateRepository"/>
  <context:exclude-filter type="aspectj" expression="..*IBatisRepository"/>
 </context:component-scan>

</beans>

 위와 같이 <context:include-filter> 태그와 <context:exclude-filter> 태그는 각각 type 속성과 expresseion 속성을 갖는데, type 속성에 따라 expression 속성에 올 수 있는 값이 달라지는데 type 속성에 입력 가능한 값을 다음과 같다

* Type 속성에 올 수 있는 값

annotation : 클랙스에 지정한 어노테이션이 적용됐는지의 여부
expression 속성에는 "org.example.SomeAnnotation"와 같은 어노테이션 이름을 입력한다.
assignable : 클래스가 지정한 타입으로 할당 가능한지의 여부.
expression 속성에는 "org.exampleSomeClass" 와 같은 타입 이름을 입력한다.

regex : 클래스 이름이 정규 표현식에 매칭되는 지의 여부.
expression 속성에는 "org\.example\.Default.*" 와 같이 정규표현식을 입력한다.

aspectj : 클래스 이름이 AspectJ 의 표현식에 매칭되는 지의 여부.
expression 속성에는 "org.example..*Service+" 와 같이 AspectJ 의 표현식을 입력한다.