Spring-2.5.6 에서 여러개의 DataSource를 사용하는 방법을 소개한다.
다음은 @Qualifier를 사용한 예이다.
Qualifier를 정의하는 방법에는 다음과 같이 두가지가 있다.
다음과 같이 두개의 데이터 소스가 선언되어 있을 때 자동 주입(Inject)하고자 한다면
<context:component-scan base-package="com.kyobobook.kflow" />
<!-- ===================================================================== -->
<!-- Transaction Configuration -->
<!-- ===================================================================== -->
<aop:config proxy-target-class="true" />
<bean id="riUniTestDataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<qualifier value="riUniTestDataSource" />
<property name="driverClassName" value="com.sybase.jdbc3.jdbc.SybDriver" />
<property name="url" value="jdbc:sybase:Tds:192.168.0.15:3000" />
<property name="connectionProperties" value="charset=eucksc;" />
<property name="username" value="dev_kf" />
<property name="password" value="dev_kf" />
</bean>
<bean id="riDataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<qualifier value="riDataSource" />
<property name="driverClassName" value="com.sybase.jdbc3.jdbc.SybDriver" />
<property name="url" value="jdbc:sybase:Tds:192.168.0.6:3000/biltis" />
<property name="connectionProperties" value="charset=eucksc;" />
<property name="username" value="dev_kb" />
<property name="password" value="dev_kb" />
</bean>
첫번째 @Resource annotation을 사용할 수 있다.
@Resource(name = "riDataSource")
public void setDataSource(DataSource dataSource) {
super.buildSqlMapClient(dataSource);
}
두번째 방법은 @Autowired와 @Qualifier 를 사용하는 방법이다.
@Autowired
public void setDataSource(@Qualifier("riDataSource") DataSource dataSource) {
super.buildSqlMapClient(dataSource);
}
위 두가지 방법의 차이점은 DI(Dependency Injection)를 어떻게 할 것인가이다. 다음은 Anyframe에서 설명하는 Dependency Injection 에 대한 내용이다.(설명이 잘되어 있어서 퍼왔으나 라이센스가 문제가 된다면 링크로 변경할 것입니다.)
특정 Bean의 기능 수행을 위해 다른 Bean을 참조해야 하는 경우 사용하는 Annotation으로는 @Autowired 또는 @Resource가 있다.
- @Autowired
Spring Framework에서 지원하는 Dependency 정의 용도의 Annotation으로, Spring Framework에 종속적이긴 하지만 정밀한 Dependency Injection이 필요한 경우에 유용하다.
- @Resource
JSR-250 표준 Annotation으로 Spring Framework 2.5.* 부터 지원 가능한 Annotation이다. Annotation 사용으로 인해 특정 Framework에 종속적인 어플리케이션을 구성하지 않기 위해서는 @Resource를 사용할 것을 권장한다. @Resource를 사용하기 위해서는 클래스패스 내에 jsr250-api.jar 파일이 추가되어야 함에 유의해야 한다.
다음은 @Resource를 사용한 예이다.
@Service public UserServiceImpl implements UserService { @Resource private UserDAO userDAO; }
@Autowired와 @Resource를 사용할 수 있는 위치는 다음과 같이 약간의 차이가 있으므로 필요에 따라 적절히 사용하면 된다.
- @Autowired : 필드, 생성자, 입력파라미터가 여러개인 메소드(@Qualifier는 메소드의 파라미터)에 적용 가능
- @Resource : 필드, 입력 파라미터가 한 개인 빈 프로퍼티 setter 메소드에 적용가능
Type-driven Injection
@Autowired는 기본적으로 type-driven injection 이다. 타입으로 참조할 빈을 찾았을 때 같은 타입의 빈이 여러 개 검색되었을 경우, @Qualifier annotation을 사용하여 구분할 수 있도록 해준다.다음은 @Qualifier를 사용한 예이다.
@Service public ProductService { @Autowired @Qualifier("electronics") private ProductCategory productCategory; }
- XML을 사용한 정의
- Annotation을 사용한 정의
<bean class="anyframe.sample.springmvc.annotation.web.
SimpleProductCategory"> <qualifier value="electronics"/> <!-- inject any dependencies required by this bean --> </bean> <bean class="anyframe.sample.springmvc.annotation.web.
SimpleProductCategory"> <qualifier value="cosmetics"/> <!-- inject any dependencies required by this bean --> </bean>
@Component @Qualifier("electronics") public class ElectronicsProductCategory implements ProductCategory { //... }
기본적으로 @Autowired가 적용된 프로퍼티는 필수이기 때문에 반드시 해당 빈이 존재해야 하지만, required 속성을 false로 설정하는 경우에는 해당되는 Bean을 찾지 못하더라도 에러가 발생하지 않는다.
@Service public UserService implements UserService { @Autowired(required=false) private UserDAO userDAO; }
- Bean name으로 Dependency Injection을 하고자 하는 경우
- Type-driven injection을 할 수 없는 Collection이나 Map 타입의 빈
@Service public UserServiceImpl implements UserService { @Resource (name="uDAO") private UserDAO userDAO; }