外观
外观
747字约2分钟
2025-02-26
Spring 中主要是通过三级缓存来处理循环依赖,这个三级缓存也可以视为 3 个 Map,其中:
首先需要了解 Bean 的生命周期,其大致分为以下 4 个步骤:
1、实例化 Bean --> 2、属性注入 --> 3、初始化 Bean --> 4、使用 --> 5、销毁 Bean
其次循环依赖就是:
Bean A 依赖 Bean B,Bean B 又依赖 Bean A,创建 Bean A 的时候会先实例化 Bean A也就是new A(),然后在进行属性填充的时候发现 A 依赖 B,那么再去创建 Bean B,先实例化,在其属性注入时发现其依赖 Bean A,从此进入循环。
引入三级缓存后解决循环依赖的思路如下:
当 Spring 容器创建 Bean A 时,会先将 A 的对象工厂放入三级缓存
当 A 需要注入 B 时,容器会尝试创建 B。同样地,B 的对象工厂也会被放入三级缓存。
当 B 需要注入 A 时(循环依赖发生),容器会首先在一级缓存中查找 A,未找到后会去二级缓存查找,再未找到则去三级缓存中通过工厂对象创建 A 的早期引用(此时 A 尚未初始化),然后将这个早期引用放入二级缓存,并从三级缓存中移除工厂对象。
B 完成属性注入和初始化后,会被放入一级缓存。
回到 A 的创建流程,此时 A 可以从一级缓存中获取到 B 的完全初始化对象进行注入,然后 A 完成初始化并放入一级缓存。
以上便解决了循环依赖。
实际上如果没有使用到 AOP(面向切面编程)的话,两层缓存就可以解决循环依赖问题,但是 AOP 是 Spring 一个很重要的特性,不可以不考虑到,像 Bean A 需要用到 AOP 的话,实际上 Bean B 依赖的是 Bean A 的代理对象,存入一级缓存的也只有 Bean A 的代理对象