Qualifier를 사용하는 annotation 기반 자동엮음(autowiring) 세부 조정
타입에 의한 자동엮음(autowiring)은 여러개의 빈이 엮여질 수 있기 때문에 선택 과정에 대해서 좀 더 제어를 할 필요가 종종 있다. 이를 하기 위한 한가지 방법은 Spring의 @Qualifier annotation을 사용하는 것이다. 가장 단순한 경우, annotation 내의 빈 이름을 써서 byName 자동엮음을 할 수 있다.
@Qualifier annotation은 또한 개개의 생성자 인자나 메소드 파라미터에 지정이 가능하다.
또한 사용자에 맞는 qualifier annotation을 만들 수도 있다. 단순하게 annotation을 정의하고 정의 내에 @Qualifier annotation을 쓰면 된다.
어떤 경우에는 value 없이 annotation을 사용하는 것으로 충분한 경우가 있다. 이는 annotation이 좀 더 일반적인 목적으로 사용되고 몇몇 다른 type의 의존성으로 적용될 때 유용하다. 예를 들어, 어떠한 인터넷 연결이 안되었을 때에 검색될 수 있는 offline 카탈로그를 제공할 수도 있다. 먼저 단순한 annotation을 다음과 같이 정의한다.
추가로 혹은 단순한 'value' 속성 대신에 이름이 지정된 속성을 받아들이는 qualifier annotation을 정의할 수도 있다. 만일 여러개의 속성 값들이 자동엮여질 필드나 파라미터에 지정된다면 빈 정의는 자동엮음 대상이라고 생각되는 속성 값 모두와 일치해야 한다. 예를 들어, 다음과 같은 annotation 정의를 생각할 수 있다.
타입에 의한 자동엮음(autowiring)은 여러개의 빈이 엮여질 수 있기 때문에 선택 과정에 대해서 좀 더 제어를 할 필요가 종종 있다. 이를 하기 위한 한가지 방법은 Spring의 @Qualifier annotation을 사용하는 것이다. 가장 단순한 경우, annotation 내의 빈 이름을 써서 byName 자동엮음을 할 수 있다.
public class MovieRecommender {
@Autowired
@Qualifier("mainCatalog")
private MovieCatalog movieCatalog;
// ...
}
@Autowired
@Qualifier("mainCatalog")
private MovieCatalog movieCatalog;
// ...
}
@Qualifier annotation은 또한 개개의 생성자 인자나 메소드 파라미터에 지정이 가능하다.
public class MovieRecommender {
private MovieCatalog movieCatalog;
private CustomerPreferenceDao customerPreferenceDao;
@Autowired
public void prepare(@Qualifier("mainCatalog") MovieCatalog movieCatalog,
CustomerPreferenceDao customerPreferenceDao) {
this.movieCatalog = movieCatalog;
this.customerPreferenceDao = customerPreferenceDao;
}
// ...
}
private MovieCatalog movieCatalog;
private CustomerPreferenceDao customerPreferenceDao;
@Autowired
public void prepare(@Qualifier("mainCatalog") MovieCatalog movieCatalog,
CustomerPreferenceDao customerPreferenceDao) {
this.movieCatalog = movieCatalog;
this.customerPreferenceDao = customerPreferenceDao;
}
// ...
}
또한 사용자에 맞는 qualifier annotation을 만들 수도 있다. 단순하게 annotation을 정의하고 정의 내에 @Qualifier annotation을 쓰면 된다.
@Target({ElementType.FIELD, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Qualifier
public @interface Genre {
String value();
}
그 다음에 자동엮음을 하려는 필드와 파라미터에 만들어진 qualifier를 적용할 수 있다.@Retention(RetentionPolicy.RUNTIME)
@Qualifier
public @interface Genre {
String value();
}
public class MovieRecommender {
@Autowired
@Genre("Action")
private MovieCatalog actionCatalog;
private MovieCatalog comedyCatalog;
@Autowired
public void setComedyCatalog(@Genre("Comedy")
MovieCatalog comedyCatalog) {
this.comedyCatalog = comedyCatalog;
}
// ...
}
다음 단계는 자동엮여질 후보 빈 정의에 해당 정보를 추가하는 것이다. <bean/> 태그의 하위 요소로 <qualifier/> 태그를 추가하고 나서 만들어진 qualifier annotation과 일치하는 'type'과 'value'를 지정한다. type은 annotation의 패키지를 포함한 전체 클래스명과 일치하거나, 이름이 충돌날 염려가 없는 경우에는 '짧은' 클래스명을 사용할 수 있다. @Autowired
@Genre("Action")
private MovieCatalog actionCatalog;
private MovieCatalog comedyCatalog;
@Autowired
public void setComedyCatalog(@Genre("Comedy")
MovieCatalog comedyCatalog) {
this.comedyCatalog = comedyCatalog;
}
// ...
}
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-2.5.xsd">
<context:annotation-config/>
<bean class="example.SimpleMovieCatalog">
<qualifier type="Genre" value="Action"/>
<!-- inject any dependencies required by this bean -->
</bean>
<bean class="example.SimpleMovieCatalog">
<qualifier type="example.Genre" value="Comedy"/>
<!-- inject any dependencies required by this bean -->
</bean>
<bean id="movieRecommender" class="example.MovieRecommender"/>
</beans>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-2.5.xsd">
<context:annotation-config/>
<bean class="example.SimpleMovieCatalog">
<qualifier type="Genre" value="Action"/>
<!-- inject any dependencies required by this bean -->
</bean>
<bean class="example.SimpleMovieCatalog">
<qualifier type="example.Genre" value="Comedy"/>
<!-- inject any dependencies required by this bean -->
</bean>
<bean id="movieRecommender" class="example.MovieRecommender"/>
</beans>
어떤 경우에는 value 없이 annotation을 사용하는 것으로 충분한 경우가 있다. 이는 annotation이 좀 더 일반적인 목적으로 사용되고 몇몇 다른 type의 의존성으로 적용될 때 유용하다. 예를 들어, 어떠한 인터넷 연결이 안되었을 때에 검색될 수 있는 offline 카탈로그를 제공할 수도 있다. 먼저 단순한 annotation을 다음과 같이 정의한다.
@Target({ElementType.FIELD, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Qualifier
public @interface Offline {
}
그 다음에 자동엮여질 필드나 속성에 annotation을 추가한다.@Retention(RetentionPolicy.RUNTIME)
@Qualifier
public @interface Offline {
}
public class MovieRecommender {
@Autowired
@Offline
private MovieCatalog offlineCatalog;
// ...
}
이제 빈 정의는 qualifier 'type' 만 필요하다.@Autowired
@Offline
private MovieCatalog offlineCatalog;
// ...
}
<bean class="example.SimpleMovieCatalog">
<qualifier type="Offline"/>
<!-- inject any dependencies required by this bean -->
</bean>
<qualifier type="Offline"/>
<!-- inject any dependencies required by this bean -->
</bean>
추가로 혹은 단순한 'value' 속성 대신에 이름이 지정된 속성을 받아들이는 qualifier annotation을 정의할 수도 있다. 만일 여러개의 속성 값들이 자동엮여질 필드나 파라미터에 지정된다면 빈 정의는 자동엮음 대상이라고 생각되는 속성 값 모두와 일치해야 한다. 예를 들어, 다음과 같은 annotation 정의를 생각할 수 있다.
@Target({ElementType.FIELD, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Qualifier
public @interface MovieQualifier {
String genre();
Format format();
}
이 경우 Format은 다음과 같은 enum 이다.@Retention(RetentionPolicy.RUNTIME)
@Qualifier
public @interface MovieQualifier {
String genre();
Format format();
}
public enum Format {
VHS, DVD, BLURAY;
}
마지막으로 빈 정의는 qualifier 값들에 대한 일치하는 것을 포함해야 한다. 이 예제에서는 또한 bean의 meta 속성이 <qualifier/> 하위 요소 대신에 사용될 수 있음을 보여준다. 가능하다면, <qualifier/> 와 그 속성들이 우선시되지만, 자동엮음 메커니즘은 qualifier 가 존재하지 않는다면 <meta/> 태그 내에서 제공되는 값을 대신 사용하게 된다. (마지막 2개의 빈 정의 참조)VHS, DVD, BLURAY;
}
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-2.5.xsd">
<context:annotation-config/>
<bean class="example.SimpleMovieCatalog">
<qualifier type="MovieQualifier">
<attribute name="format" value="VHS"/>
<attribute name="genre" value="Action"/>
</qualifier>
<!-- inject any dependencies required by this bean -->
</bean>
<bean class="example.SimpleMovieCatalog">
<qualifier type="MovieQualifier">
<attribute name="format" value="VHS"/>
<attribute name="genre" value="Comedy"/>
</qualifier>
<!-- inject any dependencies required by this bean -->
<bean>
<bean class="example.SimpleMovieCatalog">
<meta key="format" value="DVD"/>
<meta key="genre" value="Action"/>
<!-- inject any dependencies required by this bean -->
<bean>
<bean class="example.SimpleMovieCatalog">
<meta key="format" value="BLURAY"/>
<meta key="genre" value="Comedy"/>
<!-- inject any dependencies required by this bean -->
<bean>
</beans>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-2.5.xsd">
<context:annotation-config/>
<bean class="example.SimpleMovieCatalog">
<qualifier type="MovieQualifier">
<attribute name="format" value="VHS"/>
<attribute name="genre" value="Action"/>
</qualifier>
<!-- inject any dependencies required by this bean -->
</bean>
<bean class="example.SimpleMovieCatalog">
<qualifier type="MovieQualifier">
<attribute name="format" value="VHS"/>
<attribute name="genre" value="Comedy"/>
</qualifier>
<!-- inject any dependencies required by this bean -->
<bean>
<bean class="example.SimpleMovieCatalog">
<meta key="format" value="DVD"/>
<meta key="genre" value="Action"/>
<!-- inject any dependencies required by this bean -->
<bean>
<bean class="example.SimpleMovieCatalog">
<meta key="format" value="BLURAY"/>
<meta key="genre" value="Comedy"/>
<!-- inject any dependencies required by this bean -->
<bean>
</beans>
반응형
'Homo Faber > Idioms' 카테고리의 다른 글
가벼운 클래스 (0) | 2008.02.27 |
---|---|
Spring에서 annotation 태그 사용하기 (3) (0) | 2008.02.21 |
Spring에서 annotation 태그 사용하기 (1) - @Autowired (0) | 2008.02.20 |
Hibernate 테스팅 - Unitils 사용하기 (0) | 2008.02.18 |
Hibernate3 사용시 Join 테이블에 FK 이외의 컬럼이 있는 경우 매핑 (0) | 2008.02.13 |