您的位置:首页 > 编程语言 > Java开发

Spring源码阅读-BeanFactory-循环依赖

2016-12-28 00:00 756 查看
摘要: ioc注入的时候会出现循环依赖的情况,比如A有个成员变量为B,B有个成员变量为A,初始化就会循环创建,满足某些特定的条件spring是可以解决这个问题的。

循环依赖简单理解为:A依赖B,B又依赖A,创建对象的时候就会死循环,但是在单例的情况下有的循环依赖是可以解决的,下面看看spring里面的代码:

spring中解决循环依赖

上篇中创建对象的方法doCreateBean中讲到:
1 先创建bean(createBeanInstance),
2 然后填充bean的属性,这个里面就是解析了依赖对象(populateBean),

为了解决循环依赖在这两步中间把对象引用先缓存起来,看addSingletonFactory方法,这步的功能就是把已经分配内存空间的对象通过ObjectFactory放在缓存中,这里的缓存是singletonFactories :

addSingletonFactory(beanName, new ObjectFactory<Object>() {
@Override
public Object getObject() throws BeansException {
return getEarlyBeanReference(beanName, mbd, bean);
}
});
然后再填充对象属性,这是时遇到依赖的对象依赖自己,再次创建自己时候进入到getBean方法,根据前篇的文章分析知道getBean的第一步就是到缓存获取,看getSingleton方法:

protected Object getSingleton(String beanName, boolean allowEarlyReference) {
Object singletonObject = this.singletonObjects.get(beanName);
//没有对象,并且在本次创建循环里面
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
synchronized (this.singletonObjects) {
singletonObject = this.earlySingletonObjects.get(beanName);
if (singletonObject == null && allowEarlyReference) {
//获取到对象工厂
ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
if (singletonFactory != null) {
singletonObject = singletonFactory.getObject();
//提到二级缓存、工厂缓存就可以去掉了
this.earlySingletonObjects.put(beanName, singletonObject);
this.singletonFactories.remove(beanName);
}
}
}
}
return (singletonObject != NULL_OBJECT ? singletonObject : null);
}


先到单例缓存中获取

如果没获取到对象,并且在本次创建循环里面则到二级缓存获取

如果二级缓存也没有获取到对象,则到对象工厂获取,获取到对象后把对象上升到二级缓存中

解决循环依赖的必要条件

根据上面的判断可以看出要先创建一个对象,这个对象不一定要完整,但是堆内存地址已经分配,并且提前把这个引用放入到缓存中,后面其他需要依赖的对象直接可以在缓存中获取到对应的引用。

这个就是基于缓存、对象地址引用原理解决的这个问题,所以有一些不能解决循环引用的情况:

1. 用bean标签配置depends-on标签循环引用

2. 作为构造函数参数循环引用

3.非单例模式

总结

spring通过提前暴露对象内存地址到缓存中解决的循环引用
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息