由于Spring工厂创建bean的过程过于复杂,故分解为多篇文章,此篇文章分析FactoryBean的创建,以及单例FactoryBean是如何处理循环依赖的,对循环依赖作初步了解。
首先看bean工厂的继承图,首先得先熟悉下涉及到创建FactoryBean的几个类的作用,不至于后续在debug过程中“迷路”了
bean工厂uml图

AliasRegistry接口:用于管理别名的通用接口
SimpleAliasRegistry类:AliasRegistry的简单实现类,其主要属性如下:
public class SimpleAliasRegistry implements AliasRegistry {
/*有了该属性就可通过bean的别名找到bean的最终名称:如beanA的别名是beanB,而beanB的别名是beanC;则此集合会这么存储该结果:
* beanC->beanB;beanB-BeanA; 即key为别名,value为最终名称;只要通过数次循环就可通过别名找到最终名称
*/
private final Map<String, String> aliasMap = new ConcurrentHashMap<>(16);
FactoryBeanRegistrySupport类:用于管理FactoryBean实例,其主要属性如下:
//key为beanName,value为FactoryBean通过getObject方法创建的实例;
//如果是单例的bean,则会加入该缓存
private final Map<String, Object> factoryBeanObjectCache = new ConcurrentHashMap<>(16);
DefaultSingletonBeanRegistry类:这个类用于管理单例bean。这个类较为重要,处理循环依赖的相关属性都在此类;但针对于FactoryBean而言,没有使用到三级缓存;主要看singletonsCurrentlyInCreation 属性就可。其主要属性如下:
public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements SingletonBeanRegistry {
//一级缓存,key为beanName,value为创建完成的bean实例;在单例bean创建完成后都会将其加入该缓存
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);
/** 三级缓存,key为beanName,value为ObjectFactory对象,调用该对象的getObject方法就会返回还未创建完成的bean
* 那么既然bean还未创建完成,调用getObject方法返回的是什么?返回的还未创建完成的bean处于一种什么状态?
* 其实就是在bean使用默认的无参构造器实例化好了对象,但是其属性还未完成setter注入,这个状态就叫bean还未创建完成。对于Spring
* 工厂而言,只有在bean实例化完成,并且所有配置的属性已注入,并且经过所有注册的后处理器(当然可能没有注册后处理器,那就不需要处理)
* 处理后,这个bean才算创建完成。
*/
private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);
/** 二级缓存,key为beanName,value为使用无参构造器实例化的bean实例 */
private final Map<String, Object> earlySingletonObjects = new ConcurrentHashMap<>(16);
/** Set of registered singletons, containing the bean names in registration order. */
private final Set<String> registeredSingletons = new LinkedHashSet<>(256);
/** 正在创建中的beanName集合。该属性是为了解决循环依赖。 在bean实例化完成后,初始化阶段或者后处理器阶段,都会使用到该属性*/
private final Set<String> singletonsCurrentlyInCreation =
Collections.newSetFromMap(new ConcurrentHashMap<>(16));
/** 在该集合中的beanName不用检查循环依赖 */
private final Set<String> inCreationCheckExclusions =
Collections.newSetFromMap(new ConcurrentHashMap<>(16));
/** Collection of suppressed Exceptions, available for associating related causes. */
@Nullable
private Set<Exception> suppressedExceptions;
/** Flag that indicates whether we're currently within destroySingletons. */
private boolean singletonsCurrentlyInDestruction = false;
/** Disposable bean instances: bean name to disposable instance. */
private final Map<String, Object> disposableBeans = new LinkedHashMap<>();
/** 用于缓存所有内嵌bean。内嵌bean:在<constructor-arg>或者<property>标签下的<bean>标签,作为函数构造器或者set方法某个参数的值 */
private final Map<String, Set<String>> containedBeanMap = new ConcurrentHashMap<>(16);
/** key为被依赖的bean,value为依赖key的bean */
private final Map<String, Set<String>> dependentBeanMap = new ConcurrentHashMap<>(64);
/** 这个和上面相反,key为依赖value的bean,value为被key依赖的bean */
private final Map<String, Set<String>> dependenciesForBeanMap = new ConcurrentHashMap<>(64);
在此首先介绍下循环依赖
循环依赖分为2种,构造器注入循环依赖以及setter循环依赖。Spring无法解决构造器循环依赖,只解决了setter注入循环依赖。
Spring如何解决setter循环依赖?
例如如下代码:
public class BeanA {
public BeanB beanB;
public void setBeanB(BeanB beanB) {
this.beanB = beanB;
}
}
public class BeanB {
public BeanC beanC;
public void setBeanC(BeanC beanC) {
this.beanC = beanC;
}
}
public class BeanC {
public BeanA beanA;
public void setBeanA(BeanA beanA) {
this.beanA = beanA;
}
}
<bean id="beanA" class="com.example.demo.循环依赖.BeanA">
<property name="beanB" ref="beanB" />
</bean>
<bean id="beanB" class="com.example.demo.循环依赖.BeanB">
<property name="beanC" ref="beanC" />
</bean>
<bean id="beanC" class="com.example.demo.循环依赖.BeanC">
<property name="beanA" ref="beanA" />
</bean>
当容器调用getBean(“beanA”)时,Spring会进行如下操作:
1、使用BeanA的无参构造器实例化beanA,并将beanA放进“正在创建的bean中”(也就是singletonsCurrentlyInCreation 属性),再创建一个ObjectFactory对象(该对象可以使用getObject方法返回beanA)放入三级缓存(也就是singletonFactories 属性)。然后进行setter注入beanB,此时beanB还未创建;
2、使用BeanB的无参构造器实例化beaB,并将beanB放进“正在创建的bean中”(也就是singletonsCurrentlyInCreation 属性),再创建一个ObjectFactory对象(该对象可以使用getObject方法返回beanB)放入三级缓存(也就是singletonFactories 属性)。然后进行setter注入beanC,此时beanC还未创建;
3、使用BeanC的无参构造器实例化beanC,并将beanA放进“正在创建的bean中”(也就是singletonsCurrentlyInCreation 属性),再创建一个ObjectFactory对象(该对象可以使用getObject方法返回beanC)放入三级缓存(也就是singletonFactories 属性)。然后进行setter注入beanA,此时beanA已经完成实例化;故从三级缓存中获取其ObjectFactory对象,调用getObject方法获取实例化好的beanA(此时beanA实际上并未创建完成);
4、然后再注入beanB,BeanC。
AbstractBeanFactory # doGetBean
1、规范传入的name
2、从缓存中获取bean(该bean是原始状态的)
3、对获取的bean进行处理
protected <T> T doGetBean(
String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)
throws BeansException {
/* 总结这个方法:首先取消工厂前缀(&,有多个就取消多少个);再将其从bean别名转换成原始bean名称
*
* 其中取消多个工厂前缀很简单,就是循环多次,若开头是&就直接截取字符串;
* 那么规范名称呢?SimpleAliasRegistry中有别名缓存,即this.aliasMap(ConcurrentHashMap<String, String>),该属性表示从别名映射到规范
* 名称。也就是可通过该集合找到最终的原始名称
*/
String beanName = transformedBeanName(name);
Object bean;
/* 从缓存中获取原始状态的单例bean(原始状态即可能是工厂bean或者FactoryBean,而非真正需要的 bean本身)
*
* 总结这个方法:该方法使用三级缓存,若beanName不在一级缓存并且该bean在创建中,就调用二级缓存;若二级缓存仍然找不到并且该bean允许早期引用,才调用三级缓存。
*/
Object sharedInstance = getSingleton(beanName);
if (sharedInstance != null && args == null) {
//对bean进行检测,获取真正需要的bean
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}
// Check if required type matches the type of the actual bean instance.
if (requiredType != null && !requiredType.isInstance(bean)) {
try {
T convertedBean = getTypeConverter().convertIfNecessary(bean, requiredType);
if (convertedBean == null) {
throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
}
return convertedBean;
}
catch (TypeMismatchException ex) {
if (logger.isTraceEnabled()) {
logger.trace("Failed to convert bean '" + name + "' to required type '" +
ClassUtils.getQualifiedName(requiredType) + "'", ex);
}
throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
}
}
return (T) bean;
}
DefaultSingletonBeanRegistry # getSingleton:设置标识
@Override
@Nullable
public Object getSingleton(String beanName) {
//参数true设置标识允许早期依赖
return getSingleton(beanName, true);
}
DefaultSingletonBeanRegistry # getSingleton:双重检测锁单例
this.singletonObjects:保存BeanName和创建bean实例之间的关系
this.earlySingletonObjects:保存BeanName和创建bean实例之间的关系,目的是检测循环引用
this.singletonFactories:保存BeanName和创建Bean的工厂之间的关系
this.singletonsCurrentlyInCreation:?
@Nullable
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
// Quick check for existing instance without full singleton lock
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
singletonObject = this.earlySingletonObjects.get(beanName);
if (singletonObject == null && allowEarlyReference) {
synchronized (this.singletonObjects) {
// Consistent creation of early reference within full singleton lock
singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
singletonObject = this.earlySingletonObjects.get(beanName);
if (singletonObject == null) {
ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
if (singletonFactory != null) {
singletonObject = singletonFactory.getObject();
this.earlySingletonObjects.put(beanName, singletonObject);
this.singletonFactories.remove(beanName);
}
}
}
}
}
}
return singletonObject;
}
getObjectForBeanInstance:处理FactoryBean
1、检验传入的name是否以&开头 ;并且 beanInstance(从缓存获取的原始状态bean)不是FactoryBean则抛出异常;(也就是用户需要创建name对象的FactoryBean对象,但缓存中注册在该名字下的beanInstance却不是FactoryBean,所以报错)
2、检验beanInstance是否是普通bean,若是则直接返回
3、判断缓存中是否存在该FactoryBean
- 不存在则读取其BeanDefinition,若存在parent则合并父BeanDefinition,最后生成RootBeanDefinition对象
- 存在则返回
4、通过FactoryBean实例创建bean实例
this.factoryBeanObjectCache:FactoryBeans 创建的单例对象的缓存:FactoryBean 名称-》对象。
protected Object getObjectForBeanInstance(
Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) {
//若要获取的就是工厂bean,则直接返回;若用户要获取的是工厂bean,但beanInstance不是FactoryBean,则抛出异常
if (BeanFactoryUtils.isFactoryDereference(name)) {
if (beanInstance instanceof NullBean) {
return beanInstance;
}
if (!(beanInstance instanceof FactoryBean)) {
throw new BeanIsNotAFactoryException(beanName, beanInstance.getClass());
}
if (mbd != null) { mbd.isFactoryBean = true; }
return beanInstance;
}
//经过上面条件的过滤,代码来到此处说明用户需要获取的bean是FactoryBean创建的普通bean或者是普通bean
//而beanInstance可能是FactoryBean或者普通bean
//如果不是FactoryBean,则不用处理,因为其本身就是实际需要的bean,直接返回
if (!(beanInstance instanceof FactoryBean)) {
return beanInstance;
}
//对FactoryBean开始处理
Object object = null;
if (mbd != null) {
mbd.isFactoryBean = true;
}
else {
//尝试从factoryBeanObjectCache缓存中获取,该方法位于父类FactoryBeanRegistrySupport中,该父类用于管理FactoryBean
object = getCachedObjectForFactoryBean(beanName);
}
//若缓存中不存在,则直接读取beanName对应的BeanDefinition,然后进行实例化
if (object == null) {
FactoryBean<?> factory = (FactoryBean<?>) beanInstance;
if (mbd == null && containsBeanDefinition(beanName)) {
//合并BeanDefinition,并生成RootBeanDefinition返回
mbd = getMergedLocalBeanDefinition(beanName);
}
boolean synthetic = (mbd != null && mbd.isSynthetic());
object = getObjectFromFactoryBean(factory, beanName, !synthetic);
}
return object;
}
getMergedLocalBeanDefinition:合并标签的缓存
为何要合并parent的BeanDefinition?
因为在将Xml文件解析成BeanDefinition时,对于有的bean标签属性继承于parent,不合并parent属性则其bean标签属性不完善。
this.mergedBeanDefinitions:根据子beanName获取该子bean和父bean合并后的BeanDefinition
protected RootBeanDefinition getMergedLocalBeanDefinition(String beanName) throws BeansException {
// 查看合并BeanDefinition缓存中是否已经存在该BeanDefinition
RootBeanDefinition mbd = this.mergedBeanDefinitions.get(beanName);
if (mbd != null && !mbd.stale) {
return mbd;
}
//根据beanName和BeanDefinition获取合并BeanDefinition
return getMergedBeanDefinition(beanName, getBeanDefinition(beanName));
}
getMergedBeanDefinition:设置个参数而已,默认非内嵌bean
protected RootBeanDefinition getMergedBeanDefinition(String beanName, BeanDefinition bd)
throws BeanDefinitionStoreException {
return getMergedBeanDefinition(beanName, bd, null);
}
getMergedBeanDefinition
若存在父标签则合并parent标签,不存在则直接将BeanDefinition转换为RootBeanDefinition
getObjectFromFactoryBean
该方法中在创建单例bean时因为要检测循环依赖,故逻辑较多;而在创建原型bean时,就直接调用FactoryBean的getObject方法,就简单多了
涉及的属性:
inCreationCheckExclusions:标记一个bean在被加载时不需要检查循环依赖
singletonsCurrentlyInCreation:标记一个bean正在被创建
此处重点分析单例bean的创建
protected Object getObjectFromFactoryBean(FactoryBean<?> factory, String beanName, boolean shouldPostProcess) {
//若FactoryBean本身并且一级缓存存在beanName
if (factory.isSingleton() && containsSingleton(beanName)) {
synchronized (getSingletonMutex()) {//锁对象:this.singletonObjects
//从缓存中获取bean实例
Object object = this.factoryBeanObjectCache.get(beanName);
if (object == null) {
//此处调用FactoryBean的getObject方法创建对象
object = doGetObjectFromFactoryBean(factory, beanName);
//再次从缓存获取对象,如果缓存已经存在,则直接返回,而不再判断是否需要进行后处理操作
Object alreadyThere = this.factoryBeanObjectCache.get(beanName);
if (alreadyThere != null) {
object = alreadyThere;
}
else {
/*
* 总结一下这个else:其实经过上述的过程,object已经实例化并且已经初始化完毕,这个else的作用是进行后处理,后处理涉及修改object属性,也就是存在循环依赖的隐患,故需要进行循环依赖的处理。
*/
//缓存中不存在,则判断是否需要后处理
if (shouldPostProcess) {
//判断是否存在循环依赖,若true则存在,就直接返回
if (isSingletonCurrentlyInCreation(beanName)) {
return object;
}
//若不存在循环依赖则进行后处理操作
//将beanName添加到this.singletonsCurrentlyInCreation中
//本质上就是记录该bean开始被加载---》避免循环依赖
beforeSingletonCreation(beanName);
try {
//调用用户自定义的一些后处理器进行一些操作
object = postProcessObjectFromFactoryBean(object, beanName);
}
catch (Throwable ex) {
throw new BeanCreationException(...);
}
finally {
//从this.singletonsCurrentlyInCreation中移除beanName
//即表示bean加载已经结束---》避免循环依赖
afterSingletonCreation(beanName);
}
}
if (containsSingleton(beanName)) {
//若bean是单例则加入缓存
this.factoryBeanObjectCache.put(beanName, object);
}
}
}
return object;
}
}
//若bean是原型则比较简单了,直接调用getObject方法获取bean,再判断是否需要调用后处理器进行处理
else {
Object object = doGetObjectFromFactoryBean(factory, beanName);
if (shouldPostProcess) {
try {
object = postProcessObjectFromFactoryBean(object, beanName);
}
catch (Throwable ex) {
throw new BeanCreationException(...);
}
}
return object;
}
}
AbstractAutowireCapableBeanFactory # postProcessObjectFromFactoryBean:后处理器
AbstractAutowireCapableBeanFactory # applyBeanPostProcessorsAfterInitialization
遍历每个BeanPostProcessor 对象进行处理,如果在某个后置处理器将result赋值为空时,则直接终端,返回上一个不为不为空的结果
@Override
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
throws BeansException {
Object result = existingBean;
for (BeanPostProcessor processor : getBeanPostProcessors()) {
Object current = processor.postProcessAfterInitialization(result, beanName);
if (current == null) {
return result;
}
result = current;
}
return result;
}
在整个FactoryBean创建过程中,只在后处理器处理时使用了singletonsCurrentlyInCreation 属性,用于标记当时正在创建的beanName,但没有涉及到三级缓存,是因为FactoryBean没有setter注入功能。