Spring源码阅读-BeanFactory-循环依赖
2016-12-28 00:00
756 查看
摘要: ioc注入的时候会出现循环依赖的情况,比如A有个成员变量为B,B有个成员变量为A,初始化就会循环创建,满足某些特定的条件spring是可以解决这个问题的。
循环依赖简单理解为:A依赖B,B又依赖A,创建对象的时候就会死循环,但是在单例的情况下有的循环依赖是可以解决的,下面看看spring里面的代码:
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方法:
先到单例缓存中获取
如果没获取到对象,并且在本次创建循环里面则到二级缓存获取
如果二级缓存也没有获取到对象,则到对象工厂获取,获取到对象后把对象上升到二级缓存中
这个就是基于缓存、对象地址引用原理解决的这个问题,所以有一些不能解决循环引用的情况:
1. 用bean标签配置depends-on标签循环引用
2. 作为构造函数参数循环引用
3.非单例模式
循环依赖简单理解为: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通过提前暴露对象内存地址到缓存中解决的循环引用相关文章推荐
- Spring 源码阅读 BeanFactory(三) 对象的初始化 singleton 草稿
- Spring IOC/BeanFactory/ApplicationContext的工作流程/实现原理/初始化/依赖注入源码详解
- spring 源码探索--单例bean解决循环依赖问题
- Spring 源码阅读之BeanFactory
- Spring源码阅读-DefaultListableBeanFactory的属性注释翻译
- 菜鸟看spring源码(0)之BeanFactory的注册与依赖绑定
- Spring源码阅读-使用ProxyFactoryBean实现AOP
- Spring 源码阅读之BeanFactory
- Spring源码学习--Bean对象循环依赖问题解决(四)
- 从spring源码角度分析循环依赖bean的组装
- Spring源码阅读-ApplicationContext对BeanFactory的增强
- Spring源码-IOC容器(六)-bean的循环依赖
- Spring 源码阅读 BeanFactory(二) 之registerBeanDefinition方法
- Spring 源码阅读-循环依赖
- Spring 源码阅读-BeanFactory
- spring 源码解读与设计详解:4 DefaultListableBeanFactory及资源载入
- spring beans源码解读之--XmlBeanFactory
- spring 源码解读与设计详解:3 FactoryBean
- Spring源码解析 ---- 循环依赖
- spring beans源码解读之--BeanFactory的注册