Spring-bean的循环依赖

什么是Spring的循环依赖?

在 Spring 框架中,循环依赖是指两个或多个 Bean 相互依赖,形成一个闭环。

  • Setter 方法循环依赖:Bean A 通过 setter 方法注入 Bean B,Bean B 又通过 setter 方法注入 Bean A。(即@Autowired)
  • 构造器循环依赖:Bean A 需要 Bean B 的实例,而 Bean B 又需要 Bean A 的实例。

Setter 方法循环依赖

在这里插入图片描述

三级缓存

三级缓存是 Spring 处理 Setter 循环依赖的关键机制

  • Singleton Objects(一级缓存):存放已完全初始化的单例 Bean。
  • Early Singleton Objects(二级缓存):缓存早期的 Bean 对象(就是这些 Bean 已经被实例化,但是还没有被完全初始化)。也可避免重复通过工厂获取早期引用。
  • Singleton Factories(三级缓存):存储可以创建单例Bean实例的工厂,可以创建代理对象(二级缓存不能解决的),普通对象

Spring 是如何利用三级缓存解决 Bean 的循环依赖?

三级缓存是 Spring 框架中用于解决 Bean 循环依赖的一种机制。

一级缓存
在这里插入图片描述

二级缓存:
在这里插入图片描述
三级缓存

二级缓存用于存储已经创建但未完全初始化的早期 Bean 引用。但是在 Bean 被完全初始化之前,早期引用可能需要通过代理对象(如 AOP 代理)创建。三级缓存正是用于存储这种生成早期引用的工厂方法。

通过三级缓存,Spring 可以在 ObjectFactory 中定义如何创建早期引用(如处理代理),这样就可以灵活地在需要时(特别是在循环依赖情况下)提供一个代理后的早期引用给其他 Bean 使用。
在这里插入图片描述

有了三级缓存为什么还需要二级缓存?

二级缓存的引入可以防止多次使用对象工厂(ObjectFactory)创建多个对象实例,从而避免不必要的多例问题

首次访问早期引用: 当一个 Bean 正在初始化过程中(比如 A 依赖 B ,但 B 尚未完全初始化)时,Spring 会首先检查一级缓存(完全初始化的单例对象)中是否有 B。如果没有,再检查二级缓存(早期暴露的对象引用)。如果二级缓存中也没有,再通过三级缓存的 ObjectFactory 获取 B 的早期引用。 一旦通过 ObjectFactory 获取了 B 的早期引用,Spring 会将这个引用放入二级缓存。这样,后续对 B 的早期引用访问就不会再触发 ObjectFactory,而是直接从二级缓存中获取。

构造器循环依赖

三级缓存机制可以自动处理基于单例作用域的 setter 方法循环依赖,但无法解决由构造器注入引起的循环依赖。

比如:

@Component
public class A {
    private B b;

    @Autowired
    public A(B b) {
        this.b = b;
    }
}

@Component
public class B {
    private A a;

    @Autowired
    public B(A a) {
        this.a = a;
    }
}

解决方法:使用 @Lazy 注解,在构造器注入中使用 @Lazy 注解,可以推迟依赖的初始化,从而打破循环。@Lazy 注解表示在实际使用时才创建实例,而不是在启动时。

@Component
public class A {
    private B b;

    @Autowired
    // 添加注解 @Lazy
    public A(@Lazy B b) {
        this.b = b;
    }
}

@Component
public class B {
    private A a;

    @Autowired
    public B(@Lazy A a) {
        this.a = a;
    }
}

总结

  • Setter 注入循环依赖:Spring 通过三级缓存机制自动处理

  • 构造器注入循环依赖:Spring 无法自动解决,使用 @Lazy 注解


❤觉得有用的可以留个关注丫~❤

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值