Spring 註解實現Bean依賴注入之@Qualifier

三、@Qualifier:限定描述符,用於細粒度選擇候選者;

@Autowired默認是根據類型進行注入的,因此如果有多個類型一樣的Bean候選者,則需要限定其中一個候選者,否則將拋出異常

@Qualifier限定描述符除了能根據名字進行注入,更能進行更細粒度的控制如何選擇候選者,具體使用方式如下:

@Qualifier(value = "限定標識符")  
字段、方法、參數  


(1)、根據基於XML配置中的<qualifier>標籤指定的名字進行注入,使用如下方式指定名稱:

<qualifier  type="org.springframework.beans.factory.annotation.Qualifier"  value="限定標識符"/> 

其中type屬性可選,指定類型,默認就是Qualifier註解類,name就是給Bean候選者指定限定標識符,一個Bean定義中只允許指定類型不同的<qualifier>,如果有多個相同type後面指定的將覆蓋前面的。

1、準備測試Bean:

DataSource.java

package com.bean;

public interface DataSource {

	public void connection();
}
MysqlDriveManagerDataSource.java

package com.bean;

public class MysqlDriveManagerDataSource implements DataSource{

	public void connection() {
		System.out.println("mysql database connecting...");
	}

}
OracleDriveManagerDataSource.java

package com.bean;

public class OracleDriveManagerDataSource implements DataSource{

	public void connection() {
		System.out.println("oracle database connecting...");
	}

}
TestBean.java

package com.bean;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;


public class TestBean {
	
	private DataSource dataSource;
	
	@Autowired
	public void initDataSource(@Qualifier("oracleDataSource") DataSource dataSource){
		this.dataSource = dataSource;
	}
	
	public DataSource getDataSource() {
		return dataSource;
	}
}

其中TestBean.java中使用 @Qualifier還有一種方式

@Autowired
@Qualifier(value="oracleDataSource")
public void initDataSource(DataSource dataSource){
	this.dataSource = dataSource;
}

2、在Spring配置文件 添加如下Bean配置:

<bean id="testBean" class="com.bean.TestBean"/>

我們使用@Qualifier("oracleDataSource")來指定候選Bean的限定標識符,我們需要在配置文件中使用<qualifier>標籤來指定候選Bean的限定標識符“oracleDataSource”:

<bean id="mysqlDataSourceBean" class="com.bean.MysqlDriveManagerDataSource">
	<qualifier value="mysqlDataSource"/>
</bean>

<bean id="oracleDataSourceBean" class="com.bean.OracleDriveManagerDataSource">
	<qualifier value="oracleDataSource"/>
</bean>

3、測試方法如下:

@Test
public void autowiredTest(){
	TestBean bean = ctx.getBean("testBean", TestBean.class);
	DataSource dataSource = bean.getDataSource();
	if(dataSource instanceof MysqlDriveManagerDataSource){
		System.out.println("mysql");
	}else if(dataSource instanceof OracleDriveManagerDataSource){
		System.out.println("oracle");
	}
	dataSource.connection();
	
	try{
		ctx.getBean("mysqlDataSource");
	}catch(Exception e){
		if(e instanceof NoSuchBeanDefinitionException){
			System.out.println("@Qualifier不能作爲Bean的標識符");
		}
		e.printStackTrace();
	}
}

從測試可以看出使用<qualifier>標籤指定的限定標識符只能被@Qualifier使用,不能作爲Bean的標識符,如“ctx.getBean("mysqlDataSource")”是獲取不到Bean的。



(2)、缺省的根據Bean名字注入最基本方式,是在Bean上沒有指定<qualifier>標籤時一種容錯機制,即缺省情況下使用Bean標識符注入,但如果你指定了<qualifier>標籤將不會發生容錯。

1、準備測試Bean:

package com.bean;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;


public class TestBean {
	
	private DataSource dataSource;
	
	@Autowired
	@Qualifier(value="mysqlDataSourceBean")
	public void initDataSource(DataSource dataSource){
		this.dataSource = dataSource;
	}
	
	public DataSource getDataSource() {
		return dataSource;
	}
}

2、在Spring配置文件 添加如下Bean配置:

<bean id="mysqlDataSourceBean" class="com.bean.MysqlDriveManagerDataSource"/>
<bean id="oracleDataSourceBean" class="com.bean.OracleDriveManagerDataSource"/>

3、測試方法如下:

@Test
public void autowiredTest(){
	TestBean bean = ctx.getBean("testBean", TestBean.class);
	DataSource dataSource = bean.getDataSource();
	if(dataSource instanceof MysqlDriveManagerDataSource){
		System.out.println("mysql");
	}else if(dataSource instanceof OracleDriveManagerDataSource){
		System.out.println("oracle");
	}
	dataSource.connection();

}
因爲配置文件中並沒有使用 @Qualifier標籤 所以我們在bean中注入的時候是注入 bean  

@Qualifier(value="mysqlDataSourceBean")



(3)、擴展@Qualifier限定描述符註解(不帶參數):對@Qualifier的擴展來提供細粒度選擇候選者;

具體使用方式就是自定義一個註解並使用@Qualifier註解其即可使用。

 

首先讓我們考慮這樣一個問題,如果我們有兩個數據源,分別爲Mysql和Oracle,因此注入兩者相關資源時就牽扯到數據庫相關,如在DAO層注入SessionFactory時,當然可以採用前邊介紹的方式,但爲了簡單和直觀我們希望採用自定義註解方式。

 

1、擴展@Qualifier限定描述符註解來分別表示Mysql和Oracle數據源

package com.annotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

import org.springframework.beans.factory.annotation.Qualifier;

@Target({ElementType.TYPE,ElementType.FIELD,ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Qualifier
public @interface Mysql {
}
package com.annotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

import org.springframework.beans.factory.annotation.Qualifier;

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


2、準備測試Bean:

package com.bean;

import org.springframework.beans.factory.annotation.Autowired;

import com.annotation.Mysql;
import com.annotation.Oracle;

public class TestBean {
	
	private DataSource mysqlDataSource;
	
	private DataSource oracleDataSource;

	@Autowired
	public void initDataSource(@Mysql DataSource mysqlDataSource, @Oracle DataSource oracleDataSource){
		this.mysqlDataSource = mysqlDataSource;
		this.oracleDataSource = oracleDataSource;
	}
	
	public DataSource getMysqlDataSource() {
		return mysqlDataSource;
	}
	
	public DataSource getOracleDataSource() {
		return oracleDataSource;
	}
}

3、在Spring配置文件 添加如下Bean配置:

<bean id="testBean" class="com.bean.TestBean"/>

4、在Spring修改定義的兩個數據源:

<bean id="mysqlDataSourceBean" class="com.bean.MysqlDriveManagerDataSource">
	<qualifier value="mysqlDataSource"/>
	<qualifier type="com.annotation.Mysql"/>
</bean>

<bean id="oracleDataSourceBean" class="com.bean.OracleDriveManagerDataSource">
	<qualifier value="oracleDataSource"/>
	<qualifier type="com.annotation.Oracle"/>
</bean> 

5、測試方法如下:

@Test
public void autowiredTest(){
	TestBean bean = ctx.getBean("testBean", TestBean.class);
	DataSource dataSource = bean.getMysqlDataSource();
	if(dataSource instanceof MysqlDriveManagerDataSource){
		System.out.println("mysql");
	}else if(dataSource instanceof OracleDriveManagerDataSource){
		System.out.println("oracle");
	}
	dataSource.connection();
}

測試也通過了,說明我們擴展的@Qualifier限定描述符註解也能很好工作。



(3)、擴展@Qualifier限定描述符註解(帶參數):對@Qualifier的擴展來提供細粒度選擇候選者;

前邊演示了不帶屬性的註解,接下來演示一下帶參數的註解:

1、首先定義數據庫類型:

package com.enumBean;

public enum DataBase {
	ORACLE,MYSQL;
}

2、其次擴展@Qualifier限定描述符註解

package com.annotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

import org.springframework.beans.factory.annotation.Qualifier;

import com.enumBean.DataBase;

@Target({ElementType.TYPE, ElementType.FIELD, ElementType.PARAMETER})  
@Retention(RetentionPolicy.RUNTIME)  
@Qualifier  
public @interface DataSourceType {
	String ip();    //指定ip,用於多數據源情況
	DataBase database(); //指定數據庫類型
}

3、準備測試Bean:

package com.bean;

import org.springframework.beans.factory.annotation.Autowired;

import com.annotation.DataSourceType;
import com.enumBean.DataBase;

public class TestBean {
	
	private DataSource mysqlDataSource;
	
	private DataSource oracleDataSource;

	@Autowired
	public void initDataSource(@DataSourceType(ip="localhost",database=DataBase.MYSQL) DataSource mysqlDataSource, 
				   @DataSourceType(ip="localhost",database=DataBase.ORACLE) DataSource oracleDataSource){
		this.mysqlDataSource = mysqlDataSource;
		this.oracleDataSource = oracleDataSource;
	}
	
	public DataSource getMysqlDataSource() {
		return mysqlDataSource;
	}
	
	public DataSource getOracleDataSource() {
		return oracleDataSource;
	}
}

4、在Spring配置文件 添加如下Bean配置:

<bean id="testBean" class="com.bean.TestBean"/>

5、在Spring修改定義的兩個數據源:

<bean id="mysqlDataSourceBean" class="com.bean.MysqlDriveManagerDataSource">
	<qualifier value="mysqlDataSource"/>
	<qualifier type="com.annotation.DataSourceType">
		<attribute key="ip" value="localhost"/>
		<attribute key="database" value="MYSQL"/>
	</qualifier>
</bean>

<bean id="oracleDataSourceBean" class="com.bean.OracleDriveManagerDataSource">
	<qualifier value="oracleDataSource"/>
	<qualifier type="com.annotation.DataSourceType">
		<attribute key="ip" value="localhost"/>
		<attribute key="database" value="ORACLE"/>
	</qualifier>
</bean> 

6、測試方法如下:

@Test
public void autowiredTest(){
	TestBean bean = ctx.getBean("testBean", TestBean.class);
	DataSource dataSource = bean.getMysqlDataSource();
	if(dataSource instanceof MysqlDriveManagerDataSource){
		System.out.println("mysql");
	}else if(dataSource instanceof OracleDriveManagerDataSource){
		System.out.println("oracle");
	}
	dataSource.connection();
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章