1. 程式人生 > >【spring系列】- Spring的FactoryBean的基本認識

【spring系列】- Spring的FactoryBean的基本認識

FactoryBean:工廠Bean

IOC容器內部一種特殊的Bean,主要作用就是管理內部的Bean例項物件(單例/原型物件),扮演類似工廠的角色

特點:

通過Bean名稱只能獲取其生產的物件,而不是FactoryBean本身,如果需要獲取FactoryBean本身可以通過“&Bean名稱”的形式獲取

測試:
首先構建一個FactoryBean:UserFactoryBean

package com.zhiwei.factoryBean;

import org.springframework.beans.factory.FactoryBean;

public class UserFactoryBean implements FactoryBean<User> {

	/**
	 * FacotryBean生產的物件
	 */
	@Override
	public User getObject() throws Exception {
		return new User();
	}

	@Override
	public Class<User> getObjectType() {
		return User.class;
	}

	/**
	 * 判斷FactoryBean管理的物件是否是單例物件
	 */
	@Override
	public boolean isSingleton() {
		return false;
	}
}

輔助類:User

package com.zhiwei.factoryBean;

public class User {

	private String name;
	private int age;
	
	public User(){
		this("zhangsan",20);
	}
	
	public User(String name,int age){
		this.name = name;
		this.age = age;
	}
	
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	@Override
	public String toString() {
		return "User [name=" + name + ", age=" + age + "]";
	}
}

Spring配置檔案

<!-- 普通的FactoryBean -->
	<bean id="userFactoryBean" class="com.zhiwei.factoryBean.UserFactoryBean"/>

測試程式碼

ApplicationContext ac = new ClassPathXmlApplicationContext("com/zhiwei/factoryBean/applicationContext.xml");
		
		//---------獲取FactoryBean生產的物件
		Object obj  = ac.getBean("userFactoryBean");
		System.err.println("userFactoryBean物件型別:"+obj.getClass().getName());
		
		//--------獲取factoryBean本身
		obj = ac.getBean("&userFactoryBean");
		System.err.println("&userFactoryBean物件型別:"+obj.getClass().getName());
		
		//----------判斷FactoryBean管理的是否是單例物件
		System.err.println("userFactoryBean管理單例物件:"+((UserFactoryBean)obj).isSingleton());

控制檯日誌:

userFactoryBean物件型別:com.zhiwei.factoryBean.User
&userFactoryBean物件型別:com.zhiwei.factoryBean.UserFactoryBean
userFactoryBean管理單例物件:false

FactoryBean的用途

一般進行Spring和其他的ORM框架整合時一般會用到FactoryBean,例如整合Hibernate使用的LocalSessionFactoryBean,整合mybatis使用的SqlSessionFactoryBean等,一般這些FactoryBean主要用於對一些配置資訊的管理,例如資料來源

單例FactoryBean應用:
定義DatabaseFactoryBean

package com.zhiwei.factoryBean;

import org.springframework.beans.factory.FactoryBean;

/**
 * 單例模式:FactoryBean的應用
 * @author Yang ZhiWei
 *
 */
public class DatabaseFactoryBean implements FactoryBean<DatabaseConfig>{

	private  DatabaseConfig databaseConfig;
	
	public DatabaseConfig getDatabaseConfig() {
		return databaseConfig;
	}

	public void setDatabaseConfig(DatabaseConfig databaseConfig) {
		this.databaseConfig = databaseConfig;
	}

	/**
	 * 單例模式返回規定的物件
	 */
	@Override
	public DatabaseConfig getObject() throws Exception {
		
		if(null == databaseConfig){
			synchronized (databaseConfig) {
			   if(null == databaseConfig){
					databaseConfig = new DatabaseConfig();
				}
			}
		}
		return databaseConfig;
	}

	@Override
	public Class<User> getObjectType() {
		return User.class;
	}

	/**
	 * FactoryBean管理單例物件,返回true
	 */
	@Override
	public boolean isSingleton() {
		return true;
	}
}

輔助類:DatabaseConfig

package com.zhiwei.factoryBean;

/**
 * 資料庫配置資訊
 * @author Yang ZhiWei
 *
 */
public class DatabaseConfig {

	private String databaseName;
	private String ip;
	private String port;
	private String userName;
	private String passwd;

	public String getDatabaseName() {
		return databaseName;
	}

	public void setDatabaseName(String databaseName) {
		this.databaseName = databaseName;
	}

	public String getIp() {
		return ip;
	}

	public void setIp(String ip) {
		this.ip = ip;
	}

	public String getPort() {
		return port;
	}

	public void setPort(String port) {
		this.port = port;
	}

	public String getUserName() {
		return userName;
	}

	public void setUserName(String userName) {
		this.userName = userName;
	}

	public String getPasswd() {
		return passwd;
	}

	public void setPasswd(String passwd) {
		this.passwd = passwd;
	}

	@Override
	public String toString() {
		return "DatabaseConfig [databaseName=" + databaseName + ", ip=" + ip + ", port=" + port + ", userName="
				+ userName + ", passwd=" + passwd + "]";
	}
}

Spring配置檔案:

<!-- 配置資料來源 -->
	<bean id="dataSource" class="com.zhiwei.factoryBean.DatabaseConfig">
	<property name="databaseName" value="test"/>
	<property name="ip" value="127.0.0.1"/>
	<property name="port" value="3306"/>
	<property name="userName" value="userName"/>
	<property name="passwd" value="test"></property>
	</bean>
	
	<!-- 配置資料庫訪問FactoryBean -->
	<bean id="databaseFactoryBean" class="com.zhiwei.factoryBean.DatabaseFactoryBean">
	<property name="databaseConfig" ref="dataSource"/>
	</bean>

測試程式碼:

//-----------------------使用資料庫的FactoryBean
		DatabaseConfig databaseConfig = (DatabaseConfig) ac.getBean("databaseFactoryBean");
		System.out.println(databaseConfig);

控制檯日誌:

DatabaseConfig [databaseName=test, ip=127.0.0.1, port=3306, userName=userName, passwd=test]