一 概述
FactoryBean是一个接口,通过它可以达到自定义bean的实例化过程的目标,为Spring容器中Bean的实现提供了更加灵活的方式。说简单点,我们编写一个FactoryBean实现类并将其注入到Spring容器中,可以在接口抽象方法getObject的实现方法中完成特定业务的Bean的实例化。
二 应用
2.1 创建POJO
public class Person {
private String name;
public Person() {
System.out.println("【构造器】调用Person的构造器实例化");
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
2.2 实现FactoryBean
public class MyFactoryBean implements FactoryBean {
@Override
public Person getObject() throws Exception {
Person3 person = new Person();
person.setName("baby");
return person;
}
@Override
public Class<?> getObjectType() {
return Person.class;
}
@Override
public boolean isSingleton() {
return true;
}
}
2.3 配置文件
<bean id="myFactoryBean" class="com.service.MyFactoryBean"/>
2.4 启动类
public class BeanLifeCycle{
public static void main(String[] args) throws Exception{
System.out.println("现在开始初始化容器");
ApplicationContext factory = new ClassPathXmlApplicationContext("beans.xml");
System.out.println("容器初始化成功");
Object bean1 = factory.getBean("myFactoryBean");
System.out.println("名字为myFactoryBean的bean是" + bean1.getClass());
Person3 p = (Person3)bean1;
System.out.println(p.getName());
Object bean2 = factory.getBean("&myFactoryBean");
System.out.println("名字为&myFactoryBean的bean是" + bean2.getClass());
MyFactoryBean bf = (MyFactoryBean)bean2;
System.out.println(bf.getObject().getName());
System.out.println("现在开始关闭容器!");
((ClassPathXmlApplicationContext) factory).close();
}
}
2.5 日志
【构造器】调用Person3的构造器实例化
com.service.Person@4afcd809,beanName:myFactoryBean
名字为myFactoryBean的bean是class com.service.Person
baby
名字为&myFactoryBean的bean是class com.service.MyFactoryBean
【构造器】调用Person3的构造器实例化
baby
三 源码
3.1 isFactoryBean(String name)方法
public boolean isFactoryBean(String name) throws NoSuchBeanDefinitionException {
//获取beanName
String beanName = transformedBeanName(name);
//通过beanName从缓存中读取Bean实例
//这里第二个参数是false,说明最多查找到二级缓存
Object beanInstance = getSingleton(beanName, false);
if (beanInstance != null) {
//判断这个实例是否属于FactoryBean类的实例
return (beanInstance instanceof FactoryBean);
}
// No singleton instance found -> check bean definition.
//containsBeanDefinition中没当前beanName的ben定义
//父BeanFactory属于ConfigurableBeanFactory的实例
if (!containsBeanDefinition(beanName) && getParentBeanFactory() instanceof ConfigurableBeanFactory) {
// No bean definition found in this factory -> delegate to parent.
//委托父类查找是当前beanName的bean对象是否属于FactoryBean
//递归查找
return ((ConfigurableBeanFactory) getParentBeanFactory()).isFactoryBean(name);
}
//说明不在缓存中,父BeanFactory也帮不上忙
return isFactoryBean(beanName, getMergedLocalBeanDefinition(beanName));
}
3.2 transformedBeanName方法
protected String transformedBeanName(String name) {
return canonicalName(BeanFactoryUtils.transformedBeanName(name));
}
public static String transformedBeanName(String name) {
Assert.notNull(name, "'name' must not be null");
//判断name是否不含有前缀“&”
if (!name.startsWith(BeanFactory.FACTORY_BEAN_PREFIX)) {
//若没有则直接返回
return name;
}
// name含有前缀“&”,则返回将“&”去除掉后的字符串
return transformedBeanNameCache.computeIfAbsent(name, beanName -> {
do {
beanName = beanName.substring(BeanFactory.FACTORY_BEAN_PREFIX.length());
}
while (beanName.startsWith(BeanFactory.FACTORY_BEAN_PREFIX));
return beanName;
});
}
3.3 canonicalName方法
判断入参的beanName是否为别名,若是则返回真实名字;若不是,则将入参的beanName返回
//存储别名,key为别名,value为真实名字
private final Map<String, String> aliasMap = new ConcurrentHashMap<>(16);
public String canonicalName(String name)
String canonicalName = name;
// Handle aliasing...
String resolvedName;
do {
//从存储别名和真实BeanName映射的aliasMap中获取真实BeanName
resolvedName = this.aliasMap.get(canonicalName);
//resolvedName不为空,说明存在别名
//为空则不存在,不修改canonicalName的值
if (resolvedName != null) {
//使用真实BeanName覆盖canonicalName
canonicalName = resolvedName;
}
}
while (resolvedName != null);
return canonicalName;
}
3.4 singletonObjects,earlySingletonObjects和singletonFactories变量
三级缓存这个概念经常出现在各种文章上,在源码中实际上就是指代三个Map。见下面的表格:
属性名 | 缓存级别 | key | value |
---|---|---|---|
singletonObjects | 一级 | beanName | 单例 bean 对象 |
earlySingletonObjects | 二级 | beanName | 早期单例 bean 对象,可能存在属性填充 |
singletonFactories | 三级 | beanName | ObjectFactory |
三级缓存
/** Cache of singleton objects: bean name to bean instance. */
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);
/** Cache of singleton factories: bean name to ObjectFactory. */
private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);
/** Cache of early singleton objects: bean name to bean instance. */
private final Map<String, Object> earlySingletonObjects = new HashMap<>(16);
3.5 getSingleton方法
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
//查询一级缓存
Object singletonObject = this.singletonObjects.get(beanName);
//一级缓存中是否包含key为当前beanName的值
//beanName的Bean对象有没有在创建中
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
//加锁
synchronized (this.singletonObjects) {
//一级缓存中没用缓存key为当前beanName的值
//查找二级缓存中是否包含key为当前beanName的值
singletonObject = this.earlySingletonObjects.get(beanName);
//二级缓存中没用缓存key为当前beanName的值
//allowEarlyReference为true,表示允许创建早期的引用
if (singletonObject == null && allowEarlyReference) {
//查找三级缓存中是否包含key为当前beanName的值
ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
//不为空说明存在三级缓存中
if (singletonFactory != null) {
//从三级缓存中获取当前beanName
singletonObject = singletonFactory.getObject();
//将当前beanName添加到二级缓存中
this.earlySingletonObjects.put(beanName, singletonObject);
//将当前beanName移除出三级缓存
this.singletonFactories.remove(beanName);
}
}
}
}
return singletonObject;
}
3.6 FactoryBean接口
public interface FactoryBean<T> {
String OBJECT_TYPE_ATTRIBUTE = "factoryBeanObjectType";
//返回FactoryBean创建的bean实例
T getObject() throws Exception;
//返回FactoryBean创建的bean类型。
@Nullable
Class<?> getObjectType();
//返回由FactoryBean创建的bean实例的作用域是否为单例
default boolean isSingleton() {
return true;
}
}
3.7 isFactoryBean(String beanName, RootBeanDefinition mbd)方法
protected boolean isFactoryBean(String beanName, RootBeanDefinition mbd) {
//查看isFactoryBean属性中有没有定义
Boolean result = mbd.isFactoryBean;
//没有定义
if (result == null) {
//通过反射进行类型预测
Class<?> beanType = predictBeanType(beanName, mbd, FactoryBean.class);
//预测出来的类型beanType是否为FactoryBean本身、子类或子接口,如果是就返回true,否则就false
result = (beanType != null && FactoryBean.class.isAssignableFrom(beanType));
mbd.isFactoryBean = result;
}
return result;
}
4 参考文献
1)JDK7在线文档
https://tool.oschina.net/apidocs/apidoc?api=jdk_7u4
2) JDK8在线文档
https://docs.oracle.com/javase/8/docs/api/
3)Spring Framework 5 中文文档
https://www.cntofu.com/book/95/index.html
4) Bruce Eckel. Java编程思想,第4版,2007,机械工业出版社
5)方腾飞,魏鹏,程晓明. Java并发编程的艺术,第1版,2015年,机械工业出版社
6)克雷格.沃斯. Spring实战,第5版,2020年,人民邮电出版社