什么是循环依赖
循环依赖就是,A依赖B,B也依赖A,及A中有B类型的成员变量,B中也有A类型的成员变量,在创建各个对象之后需要将属性设置进去
普通的解决方式
- 创建A对象
- 将A对象放入一个正在创建的Map缓冲中
- 发现依赖B对象进行B对象的创建
- 创建B对象
- 发现有属性依赖A对象,从已经创建好和正在创建的Map缓存中获取,进行赋值
- B创建成功将对象放入创建好的Map池中
- 继续A对象的创建
从上面可以看到需要两个Map,一个存储已经创建好的,一个存储正在创建的
Spring的解决方式
Spring中在解决循环依赖的使用了三个Map
//存放已经创建好的对象(属性等所有的方法都已经设置)
private final Map<String, Object> singletonObjects = new ConcurrentHashMap(256);
//存储实例化好的对象,但是没有做一些必要操作的对象(使用SmartInstantiationAwareBeanPostProcessor来进行操作,比如需要转成AOP代理类)
private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap(16);
//存储实例化好的对象,已经做过一些必要操作的对象
private final Map<String, Object> earlySingletonObjects = new HashMap(16);
使用三个Map的原因是,考虑到有些对象在实例化好后,还必需要做一些初始化或者其他操作,比如生成代理对象,(其他对象依赖的应该都是代理对象),所以会有三个Map
所以三个Map的逻辑为:
- 先从singletonObjects取
- 不存在在从earlySingletonObjects取
- 如果earlySingletonObjects也不存在则从singletonFactories取,同时调用getObject方法来进行实例化对象的"初始化"操作,之后将对象放入earlySingletonObjects中,避免重复"初始化"
注意:所以如果依赖是通过构造函数循环依赖则会报错
思考:为什么不在实例化之后,直接”初始化“呢?而是用一种懒初始化的方式
网友评论