1 FactoryBean接口的使用
一般情况下,Spring通过反射机制利用bean的class属性指定实现类来实例化bean。在某些情况下,实例化bean过程比较复杂,如果按照传统的方式,则需要在
1 创建User对象
package com.gientech.factoryBean;
public class User {
private String id;
private String userName;
private String email;
private String password;
public User(String userName) {
this.userName = userName;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
2 创建MyFactoryBean
package com.gientech.factoryBean;
import org.springframework.beans.factory.FactoryBean;
public class MyFactoryBean implements FactoryBean<User> {
@Override
public User getObject() throws Exception {
return new User("wangmazi");
}
@Override
public Class<?> getObjectType() {
return User.class;
}
@Override
public boolean isSingleton() {
return true;
}
}
3 修改xml配置文件
<bean id="userFactory" class="com.gientech.factoryBean.MyFactoryBean">
<property name="userInfo" value="1,zhangsan,123456@163.com,123qaz"></property>
</bean>
4 测试code和截图
-
4.1 场景一:获取实现了BeanFactory接口类的对象
ApplicationContext ac = new ClassPathXmlApplicationContext("factoryBean.xml");
// 获取实现了BeanFactory接口类的对象
MyFactoryBean factoryBean = (MyFactoryBean) ac.getBean("&userFactory");
System.out.println(factoryBean);
此时factoryBean 由Spring管理,且存储于一级缓存中,如下图所示。
-
4.2 场景二:factoryBean#getObject的返回对象存储于factoryBeanObjectCache缓存中
测试code
ApplicationContext ac = new ClassPathXmlApplicationContext("factoryBean.xml");
// 获取实现了BeanFactory接口类的对象
MyFactoryBean factoryBean = (MyFactoryBean) ac.getBean("&userFactory");
System.out.println(factoryBean);
User bean2 = (User) ac.getBean("userFactory");
System.out.println(bean2.getUserName()+ " ---- " + bean2.getEmail());
bean2是通过getObjectForBeanInstance(sharedInstance, name, beanName, null); 方法创建,此时,factoryBean 由Spring管理,且存储于一级缓存中,bean2存储于factoryBeanObjectCache 缓存中。如下图所示:
-
4.3 场景三:factoryBean#getObject的返回对象为单例时,只有一个对象存储于factoryBeanObjectCache缓存中
当User.isSingleton() 返回true时, bean2 会存入factoryBeanObjectCache缓存中,bean3 会从缓存中获取,代码和截图所示。
ApplicationContext ac = new ClassPathXmlApplicationContext("factoryBean.xml");
// 获取实现了BeanFactory接口类的对象
MyFactoryBean factoryBean = (MyFactoryBean) ac.getBean("&userFactory");
System.out.println(factoryBean);
User bean2 = (User) ac.getBean("userFactory");
System.out.println(bean2.getUserName()+ " ---- " + bean2.getEmail());
User bean3 = (User) ac.getBean("userFactory");
System.out.println(bean3.getUserName()+ " ---- " + bean3.getEmail());
-
4.3 场景四:factoryBean#getObject的返回对象不为单例时,不由Spring管理,也不存储于factoryBeanObjectCache缓存中
当User.isSingleton() 返回false时,不是单例对象,bean2,bean3 不会存入factoryBeanObjectCache缓存中,bean2,bean3 都会重新创建,代码和运行截图所示。
package com.gientech.factoryBean;
import org.springframework.beans.factory.FactoryBean;
public class MyFactoryBean implements FactoryBean<User> {
private String userInfo;
public String getUserInfo() {
return userInfo;
}
public void setUserInfo(String userInfo) {
this.userInfo = userInfo;
}
@Override
public User getObject() throws Exception {
User user = new User();
String[] arr = userInfo.split(",");
user.setId(arr[0]);
user.setUserName(arr[1]);
user.setEmail(arr[2]);
user.setPassword(arr[3]);
return user;
}
@Override
public Class<?> getObjectType() {
return User.class;
}
// 此处返回为false
@Override
public boolean isSingleton() {
return false;
}
}
ApplicationContext ac = new ClassPathXmlApplicationContext("factoryBean.xml");
// 获取实现了BeanFactory接口类的对象
MyFactoryBean factoryBean = (MyFactoryBean) ac.getBean("&userFactory");
System.out.println(factoryBean);
User bean2 = (User) ac.getBean("userFactory");
System.out.println(bean2);
User bean3 = (User) ac.getBean("userFactory");
System.out.println(bean3);
factoryBeanObjectCache 截图如下图所示:
运行结果如下图所示