在 Spring 框架里,循环依赖指的是多个 Bean 之间相互依赖,从而形成一个闭环。例如,Bean A 依赖 Bean B,而 Bean B 又依赖 Bean A。Spring 主要通过三级缓存机制来处理循环依赖,下面详细介绍相关内容。
1. 三级缓存的定义
- 一级缓存(singletonObjects):这是一个 Map,用于存放已经完全初始化好的单例 Bean,这些 Bean 可以直接使用。
- 二级缓存(singletonFactories):同样是一个 Map,用于存放提前暴露的单例 Bean 工厂,这里的 Bean 处于创建过程中,还未完成初始化。
- 三级缓存(earlySingletonObjects):也是一个 Map,用于存放提前暴露的单例 Bean,这些 Bean 只是实例化了,但未完成属性注入和初始化操作。
2. 处理循环依赖的过程
- 创建 Bean A:当需要创建 Bean A 时,Spring 会先将 Bean A 的创建工厂放入三级缓存 singletonFactories 中,然后开始进行 Bean A 的实例化操作。
- 属性注入:在对 Bean A 进行属性注入时,发现它依赖于 Bean B,于是 Spring 开始创建 Bean B。
- 创建 Bean B:如同创建 Bean A 一样,Spring 先把 Bean B 的创建工厂放入三级缓存 singletonFactories 中,接着实例化 Bean B。
- 属性注入:在对 Bean B 进行属性注入时,发现它依赖于 Bean A。此时,Spring 会从三级缓存 singletonFactories 中获取 Bean A 的创建工厂,通过该工厂提前获取到 Bean A 的早期引用,并将其放入二级缓存 earlySingletonObjects 中,同时从三级缓存 singletonFactories 中移除 Bean A 的创建工厂。
- 完成 Bean B 的创建:将从二级缓存 earlySingletonObjects 中获取到的 Bean A 的早期引用注入到 Bean B 中,然后完成 Bean B 的属性注入和初始化操作,最后将 Bean B 放入一级缓存 singletonObjects 中。
- 完成 Bean A 的创建:由于 Bean B 已经创建完成,将其注入到 Bean A 中,接着完成 Bean A 的属性注入和初始化操作,最终把 Bean A 放入一级缓存 singletonObjects 中。