spring解决循环依赖
1 什么是循环依赖![循环依赖示例图](https://img-blog.csdnimg.cn/25984588020a45af9a013a4e92a5f781.png#pic_center)
最通俗的理解,当创建A对象时,有B对象的引用,同时B对象有A对象的引用。这样在创建A时依赖B,创建B时依赖A,导致对象创建失败。
2 问题解决
doGetBean(final String name, @Nullable final Class<T> requiredType, @Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {
// 首先从从缓存中获取实例
Object sharedInstance = getSingleton(beanName);
if (sharedInstance != null && args == null) {
// 。。。
} else {
// 。。。
createBean(beanName, mbd, args);
}
// 将创建完成的bean放入一级缓存
addSingleton(beanname,object)
}
由源码可知首先从缓存中获取对象,获取缓存的代码如下:
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
// 先从一级缓存中获取
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
// 从二级缓存中获取
singletonObject = this.earlySingletonObjects.get(beanName);
if (singletonObject == null && allowEarlyReference) {
synchronized (this.singletonObjects) {
singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
singletonObject = this.earlySingletonObjects.get(beanName);
if (singletonObject == null) {
// 从三级缓存中获取
ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
// 如果从三级缓存中获取到bean那么将该bean放入到二级缓存并删除三级缓存
if (singletonFactory != null) {
singletonObject = singletonFactory.getObject();
this.earlySingletonObjects.put(beanName, singletonObject);
this.singletonFactories.remove(beanName);
}
}
}
}
}
}
return singletonObject;
}
从源码分析可知,解决循环依赖的大致流程为:
1、创建A对象,并将A对象提前暴露到三级缓存中(可以参考源码)
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
2、填充属性,需要依赖B对象
3、创建B对象,并暴露到三级缓存
4、填充属性,从缓存中获取到A对象的半成品进行填充
5、创建完毕后,将B对象放到一级缓存中
6、A对象获取到B对象完成实例化
问题
为什么构造器不能解决循环依赖
bean调用构造器实例化之前,一二三级缓存并没有bean的任何信息,在实例化之后菜放入三级缓存中,因此当getBean的时候没有命中缓存
为什么多例不能解决循环依赖
如果是prototype的bean,意味着每次都要去创建对象,无法利用缓存