BeanFactory與FactoryBean差別
BeanFactory:IOC容器,管理Bean。
FactoryBean:就是一個Bean,由IOC容器管理,與普通Bean的差別就是 在IOC裡容器裡通過ID擷取的是FactoryBean中getObject方法傳回的對象,如果要擷取FactoryBean 本身,需要加上&。FactoryBean一般用于擷取執行個體化比較複雜的Bean,比如List/Set/Map等。
FactoryBean接口介紹
public interface FactoryBean<T> {
//擷取對象
T getObject() throws Exception;
//擷取對象類型
Class<?> getObjectType();
//是否單例
boolean isSingleton();
}
如何擷取FactoryBean本身?
在ID前加&
從依賴注入的源碼裡看下
關于FactoryBean在依賴注入裡的使用主要看AbstractBeanFactory的getObjectForBeanInstance,在doGetBean中被調用
protected Object getObjectForBeanInstance(Object beanInstance, String name, String beanName, RootBeanDefinition mbd) {
//如果name開頭&,但又不是factoryBean就報錯
if (BeanFactoryUtils.isFactoryDereference(name) && !(beanInstance instanceof FactoryBean)) {
throw new BeanIsNotAFactoryException(this.transformedBeanName(name), beanInstance.getClass());
//如果是FactoryBean,且name開頭不為bean,那就取getObject
} else if (beanInstance instanceof FactoryBean && !BeanFactoryUtils.isFactoryDereference(name)) {
Object object = null;
if (mbd == null) {
object = this.getCachedObjectForFactoryBean(beanName);
}
if (object == null) {
FactoryBean<?> factory = (FactoryBean)beanInstance;
if (mbd == null && this.containsBeanDefinition(beanName)) {
mbd = this.getMergedLocalBeanDefinition(beanName);
}
boolean synthetic = mbd != null && mbd.isSynthetic();
object = this.getObjectFromFactoryBean(factory, beanName, !synthetic);
}
return object;
} else {
//否則傳回自身
return beanInstance;
}
}
這個方法就三個判斷:
1、如果不是factoryBean 但是name開頭為&,那麼報錯
2、如果是FactoryBean,并且name開頭不為&,就取FactoryBean的getObject方法
3、如果是FactoryBean,并且name開頭為&,那麼傳回FactoryBean本身。
FactoryBean代碼案例
Spring提供了很多FactoryBean,比如ListFactoryBean用來執行個體化List對象,SetFactoryBean用來執行個體化Set對象,ProxyFactoryBean用來擷取AOP的代理對象。
下面來自己使用一下FactoryBean:
public class User {
private String name;
private int age;
private String sex;
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;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
@Override
public String toString() {
return String.format("name:%s,age:%s,sex:%s",name,age,sex);
}
}
-----------------------------------------------------------------------
public class UserFactoryBean implements FactoryBean<User> {
private String userInfo;
@Override
public User getObject() throws Exception {
String[] userArray = userInfo.split(",");
User user = new User();
user.setName(userArray[0]);
user.setAge(Integer.valueOf(userArray[1]));
user.setSex(userArray[2]);
return user;
}
@Override
public Class<?> getObjectType() {
return User.class;
}
@Override
public boolean isSingleton() {
return true;
}
public String getUserInfo() {
return userInfo;
}
public void setUserInfo(String userInfo) {
this.userInfo = userInfo;
}
}
-----------------------------------------------------------------------
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="user" class="com.raycloud.dmj.data.utils.UserFactoryBean">
<property name="userInfo" value="yang,25,male"/>
</bean>
</beans>
-----------------------------------------------------------------------
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("bean.xml");
System.out.println( context.getBean("user"));
System.out.println( context.getBean("&user"));
}
輸出:
name:yang,age:25,sex:male
[email protected]