Spring是如何解决循环依赖的:createBeanInstance --> addSingletonFactory
–>getSingleton
-
Spring三级缓存
singletonObjects:单例池 存放经过了完整的生命周期的bean
earlySingletonObjects:提前暴露出来的bean缓存 存放完成实例化 或者 完成aop的代理对象的bean
singletonFactories:缓存的是一个ObjectFactory,value存放的是一个函数,走wrapIfNecessary走是否需要AOP的逻辑 完成后 放到earlySingletonObjects缓存 同时这个缓存remove掉这个元素 -
看了Spring涉及的三级缓存,我们就能理解出开发者是怎样利用缓存解决循环依赖的问题了,主要就是两个地方的实例,一是生命周期中的实例化阶段,二是生命周期的初始化后的AOP的阶段。
-
接下来举例:
@Component
Class A {
@Autowired
private B b;
}
Class B {
@Autowired
private A a;
}
- A开始doCreateBean
if (instanceWrapper == null) {
// 走生命周期中的实例化 返回类型为BeanWrapper getWrappedInstance方法就会返回该bean的实例化的bean
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
// 之后进三级缓存
// 三个条件 单例,allowCircularReferences=true,A正在创建
boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences && isSingletonCurrentlyInCreation(beanName));
if (earlySingletonExposure) {
if (logger.isTraceEnabled()) {
logger.trace("Eagerly caching bean '" + beanName +
"' to allow for resolving potential circular references");
}
// 添加到三级缓存 vale传入了一个函数 getEarlyBeanReference中wrapIfNecessary走AOP
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}
- 开始注入B,先会去找doGetBean中getSingleton方法,缓存中没有找到B的bean。
然后开始进行B的doCreateBean方法,B开始实例,属性注入,注入到A时候doGetBean下面这个方法
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
// Quick check for existing instance without full singleton lock
// 先从单例池找 如果找不到 并且发现要找的这个bean正在创建中...
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) {
// 从三级缓存 取数据 getObject 执行之前lambda表达式函数 添加到二级缓存 三级缓存remove该元素
singletonObject = singletonFactory.getObject();
this.earlySingletonObjects.put(beanName, singletonObject);
this.singletonFactories.remove(beanName);
}
}
}
}
}
}
return singletonObject;
}
-
这样就可以拿到A的实例(原始对象)或者A的AOP实例(代理对象),进行注入完成B类的bean完整生命周期,A类也可以完成B的注入。
-
在wrapIfNecessary方法 会判断是否完成类AOP代理 如果提前完成了代理 不会再次代理,保证注入的与生成的bean是一个对象。
-
总结
Spring的循环依赖,只能解决没有进行特殊后置处理器的return bean(简单的bean和aop)。如果在后置处理器直接return一个新的类出来,这里就会有问题了,可以修改allowCircularReferences=false,自己控制循环依赖就可以了。