案例
@Component
public class AService {
@Autowired
private BService bService; // 依赖 BService
}
@Component
public class BService {
@Autowired
private AService aService; // 依赖 AService
}
演化一
- AService 的生命周期
- 实例化
AService
=> AService 的 raw Object - 填充属性 BService => 去单例池查找 BService => 找不到 => 创建 BService
- 填充其他属性
- 初始化后
- 添加到单例池
- BService 的生命周期
- 实例化
BService
=> BService 的 raw Object - 填充属性 AService => 去单例池查找 AService => 找不到 => 创建 AService
- 填充其他属性
- 初始化后
- 添加到单例池
问题:
这样就完成不了循环依赖,比如相互依赖,谁也找不到谁
演化二(如果存在 AOP)
- AService 的生命周期
- 实例化
AService
=> AService 的 raw Object => 加入二级缓存 - 填充属性 BService => 去单例池查找 BService => 找不到 => 去二级缓存找 => 找不到 => 创建 BService
- 填充其他属性
- 初始化后 => 是否需要 AOP => 产生 AService 的代理对象
- 添加到单例池 => 将 AService 的代理对象加入单例池
- BService 的生命周期
- 实例化
BService
=> BService 的 raw Object => 加入二级缓存 - 填充属性 AService => 去单例池查找 AService => 找不到 => 去二级缓存找 => 找到 A Raw Object
- 填充其他属性
- 初始化后
- 添加到单例池
问题:
貌似加一个二级缓存就解决了循环依赖的问题,但是如果 AService 存在 AOP 操作,那么此时 Spring 在初始化后的操作时,会产生 AService 的代理对象,然后将 AService 的代理对象加入单例池,那么问题就来了,在进行 BService 的生命周期的时候,在填充属性阶段,此时在二级缓存中找到的是 AService 的原始对象,并赋值给 BService 的属性,那么 AService 的 AOP 就失效了
演化三(如果存在 AOP)
- AService 的生命周期
- 实例化
AService
=> AService 的 raw Object => 是否需要 AOP => 提前进行 AOP => AService 的 proxy Object => 加入二级缓存 - 填充属性 BService => 去单例池查找 BService => 找不到 => 去二级缓存找 => 找不到 => 创建 BService
- 填充其他属性
- 初始化后 => 是否需要AOP => 是否已经完成了 AOP => 没有完成 => 产生 AService 的代理对象
添加到单例池 => 将 AService 的代理对象加入单例池
BService 的生命周期
- 实例化
BService
=> BService 的 raw Object => 加入二级缓存 - 填充属性 AService => 去单例池查找 AService => 找不到 => 去二级缓存找 => 找到 A Raw Object
- 填充其他属性
- 初始化后
- 添加到单例池
问题:
那么什么情况需要进行提前 AOP 呢?当 AService 存在了循环依赖的情况下,需要进行提前 AOP,那么如何判断 AService 有循环依赖的情况呢?难道要解析所有属性么?
演化四(如果存在 AOP)
- AService 的生命周期
- 实例化
AService
=> 加入 creating集合表示我正在被创建 => AService 的 raw Object=>是否需要 AOP =>提前进行 AOP =>AService 的 proxy Object=> 加入二级缓存<aService,A RawObject> - 填充属性 BService => 去单例池查找 BService => 找不到 => 去二级缓存找 => 找不到 => 创建 BService
- 填充其他属性
- 初始化后 => 是否需要AOP => 是否已经完成了 AOP => 没有完成 => 产生 AService 的代理对
- 添加到单例池 => 将 AService 的代理对象加入单例池
- BService 的生命周期
- 实例化
BService
=> BService 的 raw Object=> 加入二级缓存<bService, Braw Object> - 填充属性 AService => 去单例池查找 AService => 找不到 => 看 creating 集合中 AService 是否正在创建 => 如果是,表示 AService 出现了循环依赖 => 是否需要 AOP => 提前进行 AOP => AService 的 proxy Object~~
~~=>去二级缓存找=>找到 A Raw Object=> 将找到的对象(可能是代理对象)赋值给 AService - 填充其他属性
- 初始化后
- 添加到单例池
问题:
既然我们可以在 BService 中来判断 AService 是否存在了循环依赖的问题,并且如果存在 AOP 我们也可以提前进行 AOP 操作,那么是否意味着我们也可以提前将 AService 的代理对象加入代理池中呢?答案是否定的,原因一:此时代理对象的 target 为 null,原因二:因为可能出现 AService 有多个循环依赖,如 AService 依赖 BService 和 CService,而 BService 和 CService 都依赖 AService,那么 BService 和 CService 都会给 AService 创建一个代理对象,那么 AService 就存在了两个代理对象,那么到底哪一个代理对象可以放入单例池呢?这样是不允许的
演化五(如果存在 AOP)
- AService 的生命周期
- 实例化
AService
=> 加入 creating集合表示我正在被创建 => AService 的 raw Object - 填充属性 BService => 去单例池(一级缓存)查找 BService => 找不到 => 去二级缓存找 => 找不到 => 创建 BService
- 填充其他属性
- 初始化后 => 是否需要AOP => 是否已经完成了 AOP(从二级缓存中取出 AService) => 没有完成 => 产生 AService 的代理对
- 添加到单例池 => 将 AService 的代理对象加入单例池
- BService 的生命周期
- 实例化
BService
=> BService 的 raw Object - 填充属性 AService => 去单例池(一级缓存)查找 AService => 找不到 => 去二级缓存找 => 找不到 => 看 creating 集合中 AService 是否正在创建 => 如果是,表示 AService 出现了循环依赖 => 是否需要 AOP => 提前进行 AOP => AService 的 proxy Object => 将找到的对象(可能是代理对象)赋值给 AService => 添加到二级缓存中
- 填充其他属性
- 初始化后
- 添加到单例池
问题:
在进行提前 AOP 的时候,需要一个 AService 的原始对象,那么这个原始对象从那里获取呢?
演化六(如果存在 AOP)
- AService 的生命周期
- 实例化
AService
=> 加入 creating集合表示我正在被创建 => AService 的 raw Object => 加入三级缓存 - 填充属性 BService => 去单例池(一级缓存)查找 BService => 找不到 => 去二级缓存找 => 找不到 => 创建 BService
- 填充其他属性
- 初始化后 => 是否需要AOP => 是否已经完成了 AOP(从二级缓存中取出 AService) => 没有完成 => 产生 AService 的代理对
- 添加到单例池 => 将 AService 的代理对象加入单例池
- BService 的生命周期
- 实例化
BService
=> BService 的 raw Object - 填充属性 AService => 去单例池(一级缓存)查找 AService => 找不到 => 去二级缓存找 => 找不到 => 看 creating 集合中 AService 是否正在创建 => 如果是,表示 AService 出现了循环依赖 => 是否需要 AOP => 从三级缓存中获取 AService 的原始对象 => 提前进行 AOP => AService 的 proxy Object => 将找到的对象(可能是代理对象)赋值给 AService => 添加到二级缓存中
- 填充其他属性
- 初始化后
- 添加到单例池
================================================================================
- AService 的生命周期
- creatingSet
- 实例化 AService => 得到一个对象 => singletonFactories
- 填充属性 BService => singletonObjects 查找 => earlySingletonObjects 查找 => singletonFactories 查找 => 创建 BService
- 填充属性 CService => singletonObjects 查找 => earlySingletonObjects 查找 => singletonFactories 查找 => 创建 CService
- 初始化前
- 初始化
- 初始化后
- 加入 singletonObjects
- BService 的生命周期
- creatingSet
- 实例化 BService => 得到一个对象 => singletonFactories
- 填充属性 AService => singletonObjects 查找 => creatingSet
出现了循环依赖 => earlySingletonObjects 查找 AService => singletonFactories 查找 AService(找到了)=> 执行 lambda 表达式得到一个对象 => 加入 earlySingletonObjects - 填充其他属性
- 初始化前
- 初始化
- 初始化后
- 加入 singletonObjects
- CService 的生命周期
- creatingSet
- 实例化 CService => 得到一个对象 => singletonFactories
- 填充属性 AService => singletonObjects 查找 => creatingSet
出现了循环依赖 => earlySingletonObjects 查找 AService(找到了) - 填充其他属性
- 初始化前
- 初始化
- 初始化后
- 加入 singletonObjects
三级缓存
- 一级缓存:singletonObjects => Map
:单例池(走过完整生命周期的 bean 对象) - 二级缓存:earlySingletonObjects => Map
:保存原始或代理对象(半成品)
如果某个 bean 出现了循环依赖,就会提前把这个暂未经过完整生命周期的 bean 放入 earlySingltonObjects 中,这个 bean 如果需要 AOP,那么就把代理对象放入 earlySingltonObjects 中,否则就把这个 bean 的原始对象放入 earlySingltonObjects 中,但是不管怎么样,就是代理对象,代理对象也是没有经过完整生命周期的,所以放入 earlySingltonObjects 中,我们将这级缓存称为存放未经过完整生命周期的 bean 的缓存,二级缓存存在意义是保证出现循环依赖时依然保持单例的特性
- 三级缓存:singletonFactories => Map
>:保存原始对象,ObjectFactory 是一个 lambda 表达式,保存了原始对象,原始对象名称、原始对象的 BeanDefinition
缓存的是一个 ObjectFactory,就是一个 lambda 表达式,在每个 bean 的生产过程中,经过实例化得到一个原始对象后,都会提前基于原始对象暴露一个 lambda 表达式,并保存到三级缓存中,这个 lambda 表达式可能用到,也可能用不到,如果当前 bean 没有出现循环依赖,则用不到,当前 bean 会按自己的生命周期正常执行,执行完成后,将自己加入 singletonObjects 中,如果当前 bean 发生了循环依赖(当前正在注入 bean 正在创建中),则从三级缓存中拿到 lambda 表达式,得到的就是这个 bean 的代理对象,并把得到的对象加入二级缓存 earlySingltonObjects 中(如果当前 bean 需要 AOP,那么执行 lambda 表达式,得到的就是一个代理对象,如果无需 AOP,得到的就是一个原始对象)。三级缓存存在的意义是打破了循环依赖,以为一旦实例化后,就加入三级缓存
额外:
Set
Map