Spring 如何解决循环依赖的问题
Spring 是通过三级缓存来解决循环依赖问题,第一级缓存里面存储完整的Bean实例,这些实例是可以直接被使用的,第二级缓存存储的是实例化后但是还没有设置属性值的Bean实例,也就是Bean里面的 依赖注入还没有做,第三级缓存是用来存放 Bean工厂,它主要用来生成原始的 Bean对象,并且放到第二个缓存里面,三级缓存的核心思想,就是把Bean的实例化,和 Bean里面的依赖注入进行分离,使用一级缓存存储完整的 bean实例,采用二级缓存来存储不完整的Bean实例 ,通过不完整里的Bean实例作为突破口,解决循环依赖问题,至于第三级缓存,主要是解决代理对象的循环依赖问题。
应用场景
当我们在写 Spring Boot 项目的时候 ,如果 ServiceA 引用了 Service B, 而 Service B 也 引用了ServiceA 的话,就会出现循环依赖的问题。
我们可以在一个引用上加上一个注解:
@Lazy
@Autowired
private AdminService adminService;
就可以成功的解决这个问题
@Lazy
注解可以通过三级缓存机制来帮助解决 Spring 中的循环依赖问题。
在 Spring 中,解决循环依赖的核心机制就是三级缓存(三级缓存指的是单例池、二级缓存和三级缓存),具体包括:
- 单例池(singletonObjects):保存完全实例化的单例 bean。
- 二级缓存(earlySingletonObjects):保存提前曝光的半成品 bean 实例,主要是防止循环依赖时反复创建 bean。
- 三级缓存(singletonFactories):保存可以创建 bean 的工厂,用于处理代理对象等特殊情况。
@Lazy
注解的作用在于延迟初始化 bean。在遇到循环依赖时,Spring 会先创建一个代理对象(占位符),并将其放入三级缓存。这样,当需要注入依赖时,另一个 bean 可以通过三级缓存中的代理对象来引用它。等到真正使用这个 bean 时,才会去初始化它的实际内容,避免了循环依赖导致的初始化死锁问题。