달력

12

« 2024/12 »

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
.. .. ..

URL : http://www.infoq.com/articles/spring-2.5-part-1 번역본


JSR(Java Specification Request)-250 어노테이션에 대한 스프링 지원사항.

 

자바 플랫폼을 위한 공통 어노테이션은 자바 EE 버전 5와 함께 소개되었고 자바 SE 버전 6에서 본격화되었다. 2006 5 BEA 시스템즈는 인젝션,인터셉션,트랜잭션을 위한 JSR-250 어노테이션과 EJB 3 어노테이션(JSR-220)에 대한 지원을 포함하는 자바 EE 5 프로그래밍 모델의 스프링 기반 실행을 제공한 Pitchfork 프로젝트에 사용되었던 인터페이스21을 발표하였다.

 현재 버전 2.5 스프링 프레임워크 core @Resource,@PostConstruct,@PreDestroy를 지원한다. 이러한 스프링 어노테이션은 어떠한 환경에서도 지원된다. 어플리케이션 서버가 있든 없든 심지어 통합 테스팅 환경에서도 지원된다. 이러한 기능은 단지 스프링 post-processor를 등록하는것만으로 가능해진다.

 

<bean class="org.springframework.context.annotation.CommonAnnotationBeanPostProcessor"/>

 

@Resource 어노테이션

 

@Resource 어노테이션은 named resource DI(Dependency Injection)을 가능케한다.

이것은 전형적으로 자바 EE 어플리케이션내에서 JNDI context의 객체 범위로 번역된다.

스프링은 JNDI lookups를 통해 객체를 분석하는 용도로 @Resource 어노테이션을 사용하는 것을 지원하지 않는다. 그러나 기본적으로 @Resource 어노테이션에 기입된 이름과 일치하는 bean name(스프링에 의해 관리되는 객체)이 추가될 것이다.

다음의 예를 보면 스프링은 어노테이션 기능을 사용한 set메소드에서 빈 이름이 dataSource인 스프링에 의해 관리되는 객체에 대한 참조는 무시한다.

 

@Resource(name="dataSource")

 public void setDataSource(DataSource dataSource) {
  
this.dataSource
= dataSource;
}

 

 

 

 

 

직접적으로 필드에 @Resource 어노테이션을 기입하는 것도 가능하다. set메소드를 노출시키지 않음으로써 코드는 더 간결해지고 또한 불변성이라는 추가적인 이점도 제공받는다. 아래에 설명되어진 것과 같이 @Resource 어노테이션은 명시적인 문자열 값조차도 필요로 하지 않는다. 아무것도 주어지지 않았을 때 필드의 이름이 기본으로 사용된다.

 

@Resource
private DataSource dataSource; // inject the bean named 'dataSource'

 

set메소드에 적용시켰을 때 기본이름은 그에 대응되는 프로퍼티에 의해 결정된다. 다시 말해서 setDataSource이라는 이름의 메소드는 프로퍼티의 이름을 dataSource로 결정한다.

 

private DataSource dataSource;
@Resource
public void
setDataSource(DataSource dataSource) {
  
this.dataSource
= dataSource;
}

 

기본이름을 위해 스프링에 의해 관리되는 객체가 발견되지 않은 상태에서 주어진 이름없이 @Resource 어노테이션을 사용한다면 주입 기법은 타입일치에 의지할 것이다. 따라서 의존성 타입에 일치하는 스프링에 의해 관리되는 객체가 주입될것이다.

 이러한 특징은 CommonAnnotationBeanPostProcessorfallbackToDefaultTypeMatch 프로퍼티 값을 false(기본값은 true)로 설정함으로써 비활성화시킬수 있다.

 

<bean class="org.springframework.context.annotation.CommonAnnotationBeanPostProcessor">
   <property name="fallbackToDefaultTypeMatch" value="false"/>
</bean>

 

위에서 언급한것처럼 스프링은 @Resource으로 처리된 의존성을 분석할 때 JNDI-lookups를 지원하지 않는다. @Resource로 처리된 모든 의존성을 위해 JNDI-lookups를 사용하기 위해서는 CommonAnnotationBeanPostProcessor alwaysUseJndiLookup플래그 값을 true로 설정해야 한다(기본값은 false).

 

 

<bean class="org.springframework.context.annotation.CommonAnnotationBeanPostProcessor">
   <property name="alwaysUseJndiLookup" value="true"/>
</bean>

 

다른대안으로 resource-ref-mappings로서 짜여진 세계적인 JNDI names에 기반을 둔 lookup을 활성화시키기 위해서 @Resource 어노테이션 내에 mappedName속성을 설정해야 한다. 실제로 대상객체가 JNDI자원일 때 스프링에 의해 관리되는 객체를 참조사항으로 사용하는 것은 추천하는 방법이며 이로 인해 간접적인 조치와 향후 보다 적은 결합을 제공한다.

JNDI lookup을 다루기 위해 스프링 2.0부터 유용한 네임스페이스를 추가함으로써 스프링에 정의된 빈은 간결하고 명확해진다.

<jee:jndi-lookup id="dataSource" jndi-name="java:comp/env/jdbc/petclinic"/>

 

이러한 접근의 이점은 간접적 조치는 보다 큰 범위의 배치 유연성을 제공한다라는 점이다.예를 들면 독립 시스템 테스트 환경은 JNDI등록을 필요로 하지 않는다. 이러한 경우에 다음과 같은 빈 정의가 시스템 테스트 환경설정에서 대체안으로 주어질 수 있다.

<bean

 id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"
      p:driverClassName="${jdbc.driverClassName}"
      p:url="${jdbc.url}"
      p:username="${jdbc.username}"
      p:password="${jdbc.password}"/>

 

위의 예에서는 실질적인 JDBC연결속성이 주어진 ${placeholder}토큰들과 매치되는 키값들이 있는 속성파일로부터 분석된다. 이것은 PropertyPlaceholderConfigurer로 불려지는 스프링 BeanFactoryPostProcessor실행을 등록함으로서 이루어진다. 이것은 환경설정에 설정되어 있는 것보다 더 자주 변화할 필요가 있는 속성들을 구체화시키는데에 흔히 사용되어지는 기법이다.

 

<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
   <property name="location" value="classpath:jdbc.properties"/>
</bean>

 

스프링 2.5에서 context 네임스페이스의 추가로 인해 property placeholder 환경설정에 더 명확한 대안이 가능해진다.

 

<context:property-placeholder location="classpath:jdbc.properties"/>

 

라이프 사이클 어노테이션 : @PostConstruct @PreDestroy

 

@PostConstruct @PreDestroy 어노테이션은 스프링 초기화 작업을 수행할 메소드와 컨테이너에서 객체를 제거하기 전에 호출되는 콜백함수들을 가동시키는데에 각각 사용된다.

그러나 이러한 특징이 스프링 2.5 이전 버전에서 이와 같은 콜백함수들을 제공하는 두가지 옵션을 대신하지는 않는다. 첫번째 옵션은 스프링의 InitializingBean DisposableBean인터페이스 중 한쪽 또는 양쪽다 실행하는 것이다. 각각의 인터페이스는 하나의 콜백메소드( 각각 afterPropertiesSet() destroy() )실행을 필요로 한다. 인터페이스를 기반으로 한 접근은 이러한 인터페이스를 실행하는 모든 스프링에 의해 관리되는 객체를 자동적으로 인식하는 스프링의 능력을 이용한다. 따라서 다른 추가적인 환경설정을 필요로 하지 않는다. 반면에 스프링의 주요 목적은 가능한한 비침해적인 것에 초점을 두고 있다. 따라서 특정 스프링 인터페이스를 실행하는 것 대신에 많은 스프링 사용자들은 특정 스프링 인터페이스의 초기화와 소멸 메소드들을 제공하는 두번째 옵션을 이용해왔다. 조금 덜 비침해적이기는 하지만 이 접근의 결점은 빈 엘리먼트에 'init-method''destroy-method'(양쪽다 또는 한가지) 속성을 명시적으로 선언할 필요가 있다는 것이다. 개발자의 관리영역 외부코드에서 콜백함수들이 호출될 필요가 있을 때 뚜렷한 환경설정이 때로는 필요하다. PetClinic어플리케이션은 이러한 시나리오를 증명해준다. PetClinic어플리케이션이 자신의 JDBC 환경설정으로 실행될 때 세번째 공용 DataSource가 사용되고 'destroy-method'는 명시적으로 선언된다. 또한, 독립 커넥션 풀 DataSource는 여전히 dataSource를 위한 또 하나의 배치옵션이라는 점과 어떠한 코드 변화도 필요로 하지 않는다는 점을 주의해라.

 

<bean id="dataSource"
            class="org.apache.commons.dbcp.BasicDataSource"
            destroy-method="close"

            p:driverClassName="${jdbc.driverClassName}"
            p:url="${jdbc.url}"
            p:username="${jdbc.username}"
            p:password="${jdbc.password}"/>

 

 

스프링 2.5에서 객체가 초기화 콜백 메소드의 호출을 필요로 한다면 그 메소드는 @PostConstruct 어노테이션으로 처리될 수 있다. 예를 들면, 시작할 때 파일 목록을 올리는 것을 시작할 필요가 있는 백그라운드 작업을 상상해보아라.

 

public class FilePoller {
 
   @PostConstruct

  
public void
startPolling() {
         ...
   }
   ...
}

 

간단하게 말해서, 스프링에 의해 관리되는 객체에서 @PreDestroy로 처리된 메소드는 그 객체를 관리하는 어플리케이션 컨텍스트가 닫힐 때 호출될 것이다.

 

public class FilePoller {
    @PreDestroy

  
public void
stopPolling() {
           ...
   }
   ...
}

 

JSR-250 어노테이션을 위한 추가적인 지원과 함께 현재 스프링 2.5는 이전의 두가지 라이프 사이클 메소드 양자의 강점을 결합시킨다. 메소드에 @PostConstruct @PreDestroy를 기입하는것은 스프링 관리 컨텍스트내에 있는 콜백함수들을 호출하기에 충분하다. 다시 말해서 추가적인 XML기반의 환경설정이 불필요하다. 동시에 어노테이션은 자바언어의 일부이다.(그리고 심지어는 자바 SE 버전 6에 포함된다.) 그러므로 구체적인 스프링 개입은 필요없다. 어노테이션은 다른 환경내에서 이해되어야만 의미론을 지적하는 추가적 이점도 가지고 있고, 시간이 경과할수록 자바 개발자들은 제3자 라이브러리에서 더 빈번히 사용된 이러한 어노테이션들을 보게 될것이다. 결국, 어노테이션 기반의 라이프 사이클 콜백함수들의 한가지 흥미로운 점은 하나 이상의 메소드가 둘 중의 어느 한쪽 어노테이션을 지닐수 있고, 어노테이션 처리된 모든 메소드들은 호출될것이라는 점이다. 위에 서술된 @Resource, @PostConstruct, @PreDestroy 어노테이션들의 모든 기능을 활성화시키기 위해서 이전에 보여준 것처럼 스프링의 CommonAnnotationBeanPostProcessor을 위한 하나의 빈 정의를 제공한다. 하나의 엘리먼트가 CommonAnnotationBeanPostProcessor를 등록하지 않는 것을 포함하여 스프링 2.5에서 더 정확한 옵션은 새로운 context 네임스페이스를 사용하는 것이다.

 

<context:annotation-config/>

 

그러나 아래 섹션에 서술된것처럼 autowiring기능을 가능하게 할 것이다. 심지어 CommonAnnotationBeanPostProcessor@WebServiceRef@EJB 어노테이션을 지원한다. 이러한것들은 기업 통합을 위한 스프링 2.5의 새로운 특징을 싣고 있는 이 연속출판물의 세번째 기사에 잘 나와있다.

 

Fine-Grained Autowiring with Annotations

 

스프링의 autowiring지원 문서는 종종 autowiring기법의 사소한 경고를 언급한다. 스프링 2.5 이전 버전에서는 autowiring은 다른 많은 접근(생성자, 타입 set 메소드, 이름 set 메소드,  자동검색(스프링이 생성자나 타입 set 메소드 둘 중 하나를 autowire하는 것을 선택) )으로 설정될 수 있었다. 이러한 다양한 옵션들은 높은 등급의 유연성을 가지고 있다. 그러나 이러한 옵션들이 뛰어난 관리능력을 자랑하지는 않는다. 다시 말해서 스프링 2.5버전 이전에는 객체의 set메소드의 명확한 부분을 autowire하는 것 또는 타입에 의한 몇가지 속성과 이름에 의한 다른것들을 autowire하는 것이 가능하지 않았다. 결과적으로 많은 스프링 사용자들은 프로토타이핑과 테스팅에 적합한 autowiring의 이점들을 인지해왔다. 그러나 이러한 이점들이 생산에 있어서 유지보수 시스템에 봉착하면 대부분의 사람들은 명확한 환경설정에 추가된 여러가지 것들이 꽤 가치가 있는 설명이라는점에 동의한다.

 그러나 극적으로 스프링 2.5는 전망을 변화시킨다. 위에 서술된것처럼 autowiring선택은 JSR-250 @Resource 어노테이션이 각각의 메소드나 필드에 이름붙은 자원들의 autowiring을 가능하게 하는 지원을 받으면서 확장되어왔다. 그러나 @Resource 어노테이션은 홀로 몇가지 한계점을 가지고 있다. 그 결과 스프링 2.5는 추가적으로 제어수준을 높이기 위해 @Autowired 어노테이션을 소개한다. 이 부분에서 서술되어진 기능들을 활성화시키기 위해  하나의 빈 정의를 등록하라.

 

<bean class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor/>

 

 

다른방도로 context 네임스페이스는 이전에 우리에게 보여준 것처럼 더 정확한 대안을 제공한다. 이것은 이 기사에서 논의되었던 post-processor(

AutowireAnnotationBeanPostProcessor CommonAnnotationBeanPostProcessor)과 스프링 2.0에서 소개되었던 어노테이션 기반 post-processor(

RequireAnnotationBeanPostProcessor PersistenceAnnotationBeanPostProcessor)를 활성화시킬것이다.

 

<context:annotation-config/>

 

@Autowired 어노테이션으로 인해 타입매치에 의한 의존성 주입이 가능해졌다. 이 점은 필드와 생성자 그리고 메소드들에 적용된다. 사실상, autowired 메소드들은 set메소드일 필요는 없고 심지어 여러 개의 파라미터를 받아들일 수 있다. 다음은 사용가능한 용법이다.

 

@Autowired
public void setup(DataSource dataSource, AnotherObject o) { ... }

 

기본적으로, @Autowired 어노테이션으로 표시된 의존성들은 필요한것으로 취급된다. 그러나 required속성을 false값으로 설정함으로서 @Autowired 어노테이션으로 표시된 의존성의 어떤것이든 마음대로 선언하는 것이 가능하다.

 다음의 예와 같이 SomeStrategy타입의 스프링에 의해 관리되는 객체가 context안에서 발견되지 않는다면 DefaultStrategy가 사용될 것이다.

 

@Autowired(required=false)
private SomeStrategy strategy = new DefaultStrategy();

 

스프링 컨텍스트가 예상된 타입의 한가지 객체보다 더 많은 객체를 포함하고 있을 때 타입에 의한 autowiring은 분명히 모호함을 발생킬 수 있다.

기본적으로, 필요한 의존성을 위해 하나의 빈이 없다면 autowiring기법은 동작하지않을것이다. 마찬가지로 임의의 모든 속성들에 대해 한가지 이상의 후보자가 존재하다면 autowiring기법은 동작하지 않을것이다. (후보자가 없거나 임의로 선택가능한 후보자가 존재하다면 autowiring기법은 간단히 그 속성들을 스킵할 것이다.) 이러한 충돌을 피하기 위한 여러가지 환경설정 옵션이 있다.

컨텍스트내에 주어진 타입의 primary 인스턴스가 있을 때 그 타입을 위한 빈 정의는 primary속성을 포함해야 한다. 이러한 접근은 다른 인스턴스들이 컨텍스트안에서 유효할 때 잘 동작한다. 그러나 비primary 인스턴스들은 항상 정확하게 설정된다.

 

<bean id="dataSource" primary="true" ... />

 

더 엄격한 관리가 필요할 때 모든 autowired 필드,생성자 인수,메소드 파라미터는 추가적으로 @Qualifier 어노테이션 처리된다. 스프링이 이름에 의한 매치를 시도할 경우 Qualifier는 문자열값을 포함한다.

 

@Autowired
@Qualifier("primaryDataSource")

private DataSource dataSource;

 

@Qualifier가 따로 분리된 어노테이션으로 존재하는 주원인은 @Autowired 어노테이션이 생성자나 그 자신의 메소드에서 유효할 때 생성자 인수나 메소드 파라미터에 적용될 수 있도록 하기 위해서이다.

 

@Autowired
public void setup(@Qualifier("primaryDataSource") DataSource dataSource, AnotherObject o) { ... }

 

@Qualifier가 따로 분리된 어노테이션이라는 사실은 심지어 커스터마이제이션에 관련된 더 많은 이점을 제공한다. 또한 사용자 정의 어노테이션은 autowiring프로세스에서 qualifier의 역할을 수행한다. 이것을 충족시키기 위한 가장 간단한 방법은 메타 어노테이션으로서 @Qualifier와 커스텀 어노테이션을 기입하는것이다.

 

@Target({ElementType.FIELD,ElementType.PARAMETER,ElementType.TYPE, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Qualifier

public @interface VetSpecialty { ... }

 

커스텀 어노테이션들은 임의로 이름에 의한 매치값을 포함할 수도 있다. 그러나 더 흔하게 marker 어노테이션으로서 사용되거나 qualifier 프로세스에 몇가지 추가적인 의미를 제공하는 값을 정의한다. 예를 들면 아래의 인용구는 타입이 일치되는 것들 중에서 적합한 후보자를 가지고 autowire처리되어야만 하는 필드를 묘사한다.

 

 

@Autowired
@VetSpecialty("dentistry")

private Clinic dentistryClinic;

 

이러한 의존성 해결책으로서 XML 환경설정을 사용할 때 qualifier 부엘리먼트들은 빈정의에 추가된다. component-scanning부분에서 비XML 대체안이 소개될것이다.

 

<bean id="dentistryClinic" class="samples.DentistryClinic">
<qualifier type="example.VetSpecialty" value="dentistry"/>
</bean>

 

@Qualifier에 있는 모든 의존성을 피하기 위해서라면 스프링 컨텍스트에 CustomAutowireConfigurer빈을 정의하고 모든 커스텀 어노테이션 타입들을 직접적으로 등록하라.

 

<bean class="org.springframework.beans.factory.annotation.CustomAutowireConfigurer">
   <property name="customQualifierTypes">
              <set>
                          <value>example.VetSpecialty</value>
              </set>
   </property>
</bean>

 

커스텀 qualifier가 명확하게 선언되었기 때문에 @Qualifier 메타 어노테이션은 더 이상 필요치 않다.

 

@Target({ElementType.FIELD,ElementType.PARAMETER,ElementType.TYPE, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface VetSpecialty { ... }

 

관련문서에서는 심지어 AutowiredAnnotationBeanPostProcessor를 설정할 때@Autowired 어노테이션 자체를 위치시키는 것도 가능하다고 말한다.

 

<bean class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor">
<property name="autowiredAnnotationType" value="example.Injected"/>
</bean>

 

대개의 경우에 이름에 의한 매치나 다른 의미값들의 옵션들로 결합된 marker 커스텀 어노테이션을 정의하는 능력은 autowiring프로세스의 좋은 관리를 해내기에 충분해야한다. 그러나 스프링은 qualifier 어노테이션들에서 많은 임의의 속성을 지원한다. 예를 들면, 다음은 매우 좋은 qualifier의 가상의 예이다.

 

@SpecializedClinic(species="dog", breed="poodle")

private Clinic poodleClinic;

 

커스텀 qualifier 실행은 이러한 속성들을 정의한다

 

@Target({ElementType.FIELD,ElementType.PARAMETER,

ElementType.TYPE, ElementType.ANNOTATION_TYPE})

@Retention(RetentionPolicy.RUNTIME)

@Qualifier

public @interface SpecializedClinic {
 
   String species();

 
  
String breed();

}

 

커스텀 qualifier의 속성들은 XML 빈 정의내에서 qualifier 어노테이션의 attribute 부엘리먼트에 매치된다. 이러한 요소들은 key/value쌍들을 제공하기 위해 사용된다.

 

<bean id="poodleClinic" class="example.PoodleClinic">
   <qualifier type="example.SpecializedClinic">
              <attribute key="species" value="dog"/>

<attribute key="breed" value="poodle"/>
 </qualifier>

</bean>

 

여태까지 설명된 모든 autowiring은 하나의 객체를 위한것이지만 collection도 지원받는다. 언제든지 컨텍스트내에서 모든 확실한 타입의 스프링에 의해 관리되는 객체들을 얻는것은 필요하고 다만 @Autowired 어노테이션을 엄격하게 type이 설정된 collection에 추가해라.

 이 부분에서 주목할만한 가치가 있는 마지막 한가지 특징은 스프링의 Aware 인터페이스를 대신하는 autowiring의 사용이다. 스프링 2.5 이전 버전에서는 객체가 스프링 컨텍스트의 ResourceLoader에 대한 참조를 필요로 한다면 그 객체는 스프링이 setResourceLoader(ResourceLoader resourceLoader) 메소드를 이용하여 이러한 의존성을 제공하는 것을 허용하기 때문에 ResourceLoaderAware를 실행할 수 있다.
 
이와 같은 기법은 스프링 관리 MessageSource와 심지어 그 자신의 ApplicationContext에 대한 참조를 얻는데에도 적용된다. 스프링 2.5 사용자들을 위해서 이러한 기법은 지금 autowiring을 통하여 완벽하게 지원받는다.(주의 : 스프링에 뚜렷이 나타난 이러한 의존성들의 결과는 항상 조심스럽게 다루어져야 하고 일반적으로 비즈니스 로직과 확실하게 분리된
infrastructure코드 안에서만 사용되어야 한다. )

 

@Autowired
private
MessageSource messageSource;
 
@Autowired
private
ResourceLoader resourceLoader;
 
@Autowired
private ApplicationContext applicationContext;

 

 

Auto-Detection of Spring Components

 

 스프링 버전 2.0을 시작으로 스프링은 데이터 액세스 코드 표시로 적합한 @Repository 어노테이션을 포함하고 있는 stereotype 어노테이션들의 개념을 소개했다. 스프링 2.5는 통상적인 3-tier 아키텍처(데이터 액세스 객체,서비스,웹 컨트롤러)를 위해 지정된 역할을 완성하기 위해 두가지 새로운 어노테이션(@Service @Controller)을 추가했다. 또한 스프링 2.5는 다른 stereotype들이 논리적으로 확장시키는 제네릭 @Component 어노테이션을 소개한다. 정확하게 어플리케이션 역할을 지시함으로서 이러한 stereotypes는 스프링 AOP와 이러한 역할에 기반을 두고 어노테이션 처리된 객체들에 추가적인 기능을 제공하는 post-processors의 사용을 촉진한다. 예를 들면 스프링 2.0@Repository 어노테이션을 실행하는 모든 객체들에 적합한 데이터 액세스 예외 번역을 자동적으로 가능하게 하는PersistenceExceptionTranslationPostProcessor을 소개했다.

또한 이와 동일한 어노테이션들은 스프링의 또 하나의 새로운 특징(클래스패스에 있는 컴포넌트들의 auto-detection)과 관련하여 사용될 수 있다. 전통적으로 XML이 스프링 메타데이터를 위해 가장 인기있는 형식이었음에도 불구하고, 이것은 유일한 선택사항이 아니다. 사실, 스프링 컨테이너의 내부 메타데이터 표현은 순수 자바이고 XML이 스프링에 의해 관리되는 객체를 정의하기 위해 사용될 때 이러한 정의들은 인스턴스화 과정이전에 해석되고 자바 객체들로 변환된다. 스프링 2.5의 한가지 중요한 새로운 능력은 소스레벨 어노테이션으로부터 메타데이터를 읽는 것을 지원한다는 점이다. 이제까지 기술된 autowiring기법은 의존성들을 주입시키는 기능을 하는 어노테이션 메타데이터를 사용한다. 그러나 여전히 각 스프링에 의해 관리되는 객체의 실행 클래스들을 제공하기 위해 적어도 최소의 빈 정의 등록을 필요로 한다. Component scanning 기능은 XML에서 최소한의 빈 정의 필요성마저도 없앨 수 있다.

위에서 보여진 바와 같이, 스프링의 어노테이션 주도의 autowiring은 좋은 제어를 희생시키는 것없이 XML의 양을 상당히 줄일 수 있다. Component 검색기법은 추가적으로 이러한 기법을 가지고 있다. XML에 있는 환경설정을 완벽하게 탈취하는 것은 필요하지 않다. 오히려 component scanning은 전반적인 환경설정을 간단히 하기 위해 XML 메타데이터를 옆에 두고 동작할 수 있다. XML을 결합하는 이 가능성과 어노테이션 주도의 기법은 PetClinic 샘플 어플리케이션 2.5 버전의 설명에서 볼 수 있듯이 균형잡힌 접근인 셈이다.

그 점에서 하부구조의 components(데이터 소스, 트랜잭션 매니저등)가 위에서 설명한것과 같이 구체화된 프로퍼티들과 함께 XML에서 정의된다. 데이터 액세스 tier 객체들은 또한 XML에서 부분적으로 정의된다. 그러나 그것들의 환경설정은 의존성 주입을 간단히 하기위해@Autowired 어노테이션을 이용한다. 결국, tier 컨트롤러들은 XML에서 명확하게 전혀 정의되지 않는다. 대신에 모든 웹 컨트롤러들의 auto-detection을 가동시키기 위해 아래와 같은 환경설정이 사용된다.

 

<context:component-scan base-package="org.springframework.samples.petclinic.web"/>

 

base-package 속성이 주어진다는 점을 주의해라. Component-scanning을 위한 기본 매칭룰은 패키지안에 있는 클래스들의 모든 스프링 stereotype 어노테이션들을 순환적으로 탐색할것이다.(다수의 패키지들은 콤마(,)로 분리된 리스트에서 제공받을 수 있다.) 그러므로 PetClinic 샘플 어플리케이션을 위한 다양한 컨트롤러 실행들은 전부 @Controller(스프링의   고유 stereotype들중의 한가지) 어노테이션 처리된 것들이다. 여기에 예가 있다.

 

@Controller
public class ClinicController {
 
  
private final Clinic clinic
;
 
   @Autowired
  
public
ClinicController(Clinic clinic) {
              
this.clinic
= clinic;
   }
 ...

 

 만약 자동 탐색된 components들이 XML에 정의되어 있다면 그것들은 스프링 컨테이너에 등록된다. 위에서 서술된것처럼 이러한 객체들은 어노테이션 주도의 autowiring을 사용한다.

 component탐색기의 매칭룰은 타입,어노테이션,AspectJ,이름패턴을 위한 정규식에 기반을 둔 components를 포함하거나 배제하는 용도로 쓰이는 필터들로 커스터마이즈될 수 있다. 기본 stereotypes는 비활성화될 수 있다. 예를 들면, 테스트 환경설정은 기본 stereotypes를 무시할 수도 있고 그 대신 Stub로 시작하는 이름을 가지거나 @Mock 어노테이션을 포함하는 모든 클래스들을 자동검색한다.

 

<context:component-scan base-package="example" use-default-filters="false">
   <context:include-filter type="aspectj" expression="example..Stub*"/>
   <context:include-filter type="annotation" expression="example.Mock"/>
</context:component-scan>

 

 게다가 타입 일치 규정들은 제외필터들과 같이 관리될 수 있다. 예를 들면, @Repository 어노테이션을 제외한 기본필터들에 의지하기 위해 exclude-filter를 추가하라.

 

<context:component-scan base-package="example">

<context:exclude-filter

type="annotation" expression="org.springframework.stereotype.Repository"/>

</context:component-scan>

 

커스텀 타입들을 등록시키는 여러가지 방법들로 component scanning을 확장시키는 것이 가능하다. Stereotype 어노테이션은 가장 간단한 선택사항이고 이로 인해 stereotype의 개념은 확장성이 있다. 이전에 언급했듯이 @Component@Repository,@Service,@Controller 어노테이션들이 논리적으로 확장시키는 제네릭 stereotype 지시어이다. 마침 @Component는 메타 어노테이션으로서 제공된다. (. 다른 어노테이션에 선언된 어노테이션) 그리고 @Component 메타 어노테이션을 가지고 있는 모든 커스텀 어노테이션은 탐색기의 기본 매칭룰에 의해 자동적으로 탐색될것이다.

@PostConstruct@PreDestroy 라이프 사이클 어노테이션 부분에서 서술된 가상의 백그라운드 작업을 상기하라. 아마도 어플리케이션은 그와 같이 많은 백그라운드 작업을 가지고 있고 이러한 작업 인스턴스들은 스프링 컨텍스트에 등록되기 위해 전형적으로 XML 빈 정의를 필요로 하고 제때에 호출되는 그들의 라이프 사이클 메소드들을 가지고 있다.

Component scanning으로 인해 더 이상 명시적인 XML 빈 정의는 필요하지 않다. 만약 모든 백그라운드 작업이 같은 인터페이스를 실행하거나 명명규칙을 따른다면 include-filters가 사용될 수 있다. 그러나 더 단순한 접근은 이러한 작업 객체들을 위한 어노테이션을 생성하고 @Component 메타 어노테이션을 제공하는 것이다.

 

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component

public @interface
BackgroundTask {
   String value()
default ""
;
}

 

그 다음에 모든 백그라운드 작업의 클래스 정의에서 커스텀 stereotype 어노테이션을 제공하라.

 

@BackgroundTask
public class FilePoller {
 
   @PostConstruct
  
public void
startPolling() {
              ...
   }
 
   @PreDestroy
  
public void
stopPolling() {
              ...
   }
   ...
}

 

 

그 대신 제네릭 @Component 어노테이션이 제공되어 왔지만 커스텀 어노테이션 기법이 의미심장한 특정 도메인 이름들을 사용할 기회를 제공한다. 이런 특정 도메인 어노테이션들은 이러한 작업들의 할동을 감시하는 충고를 추가하기 위한 모든 백그라운드 작업들을 확인하기 위해 AspectJ pointcut식을 사용하는 것과 같은 추가적인 기회를 제공한다.

 기본적으로 component가 탐지될 때 스프링은 자격이 없는 클래스 이름을 사용하여 자동적으로 빈 이름을 생성한다. 이전의 예에서 생성된 빈 이름은 filePoller였다. 그러나 스 프링의 stereotype 어노테이션들(@Component, @Repository, @Service, or @Controller)중의 한가지로 어노테이션 처리된 모든 클래스나 메타 어노테이션으로서 @Component를 사용하여 어노테이션 처리된 다른 모든 어노테이션들을 위해 value속성은 stereotype 어노테이션에 적합하게 기입될 수 있고, 인스턴스는 빈 이름으로서 그 값을 가지고 있는 컨텍스트에 등록될 것이다. 다음의 예에서 보듯이 기본으로 생성된 이름인 simpleJdbcClinic 대신 petClinic이다.

 

@Service("petClinic")
public class SimpleJdbcClinic {
   ...
}

 

마찬가지로 FilePoller의 수정된 버전을 위해 생성된 빈 이름은 filePoller 대신에 poller이다.

 

@BackgroundTask("poller")
 public class FilePoller {
   ...
}

 

모든 스프링에 의해 관리되는 객체들이 기본적으로 싱글톤 인스턴스들로 취급되는 동안, 객체에 적합한 교대의 scope을 구체화하는 것은 때때로 필요하다. 예를 들면, tier에서 스프링에 의해 관리되는 객체는 request 또는 session의 범위안에 있게 된다. 커스텀 scope이 어플리케이션 컨텍스트에 등록될 수 있도록 하기 위해서 현재 스프링 버전 2.0 scope기법은 확장성이 있다. XML환경설정 안에서 scope의 이름과 scope속성을 포함하는 것은 간단하다.

 

<bean id="shoppingCart" class="example.ShoppingCart" scope="session">
   ...
</bean>

 

스프링 2.5 @Scope 어노테이션을 제공함으로써 탐지된 component를 위한 동일한 기능이 완성되었다.

 

@Component
@Scope("session")

public class
ShoppingCart {
   ...
}

 

여기서 마지막 주제는 component-scanning을 사용할때 qualifier어노테이션의 간소화이다. 이전 설명에서 아래의 객체는 커스텀 qualifier 어노테이션과 함께 autowiring의 예로서 사용되었다.

 

@VetSpecialty("dentistry")
private Clinic dentistryClinic;

 

똑같은 예는 의존성을 위해 의도적으로 대상이 되는 빈 정의의 XML내에 있는 qualifier 엘리먼트의 사용을 특색으로 삼았다. Component-scanning을 사용할 때 XML 메타 데이터는 필요하지 않다. 대신 커스텀 qualifier 대상 클래스 정의에서 타입 레벨 어노테이션으로서 포함될 수도 있다. 의존성이 나타나면서 탐지된 @Repository 인스턴스를 가지고 있는 예이다.

 

@Repository
@VetSpecialty("dentistry")

public class DentistryClinic implements
Clinic {
   ...
}

 

마지막으로 속성들을 가지고 있는 커스텀 qualifier 어노테이션들을 언급한 이전의 예를 위해 의존 대상과 동등한 가치를 지닌 비XML은 아래와 같다.

 

@Repository
@SpecializedClinic(species="dog", breed="poodle")

public class PoodleClinic implements
Clinic {
   ...
}



'I.lib() > I.lib(Spring)' 카테고리의 다른 글

Eclipse 3.6 Helios에 STS 설치하기  (1) 2011.04.26
CronTrigger (잡 스케쥴링)  (1) 2010.04.08
Spring 트랜잭션 격리 수준, 전달 행위의 값  (0) 2010.04.02
AOP 용어  (0) 2010.03.26
Spring ppt 모음  (1) 2010.03.24
.
:
Posted by .07274.