Springboot的bean的循环依赖问题

循环依赖指的是两个或多个 Bean 之间互相依赖,进而形成一个闭环。

一、循环依赖的示例

1. 构造器注入引发的循环依赖

当两个 Bean 通过构造器实现互相注入时,就会造成循环依赖。

@Component
public class A {
    private final B b;

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

@Component
public class B {
    private final A a;

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

问题分析

  • Spring 在创建 Bean A 的时候,需要先注入 Bean B。
  • 而创建 Bean B 时,又得先注入 Bean A。
  • 这样就形成了一个死循环,最终导致 BeanCurrentlyInCreationException 异常。
2. Setter 注入引发的循环依赖(Spring 可自动解决)
@Component
public class A {
    private B b;

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

@Component
public class B {
    private A a;

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

解决原理

  • Spring 采用三级缓存机制来处理 setter 注入的循环依赖。
  • 先将未完全初始化的 Bean 放入二级缓存,供其他 Bean 引用。
  • 等 Bean 完全初始化之后,再将其移至三级缓存。
3. 字段注入引发的循环依赖
@Component
public class A {
    @Autowired
    private B b;
}

@Component
public class B {
    @Autowired
    private A a;
}

说明
字段注入本质上和 setter 注入类似,Spring 也能够自动解决这种循环依赖问题。

二、循环依赖的解决办法

1. 重构代码,消除循环依赖

这是解决循环依赖问题的最佳方式。可以把公共逻辑提取出来,创建一个新的组件。

@Component
public class CommonService {
    public void doSomething() {
        // 公共逻辑
    }
}

@Component
public class A {
    private final CommonService commonService;

    @Autowired
    public A(CommonService commonService) {
        this.commonService = commonService;
    }
}

@Component
public class B {
    private final CommonService commonService;

    @Autowired
    public B(CommonService commonService) {
        this.commonService = commonService;
    }
}
2. 使用 @Lazy 注解延迟加载
@Component
public class A {
    private final B b;

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

作用

  • 在注入 Bean B 时,不直接创建实例,而是注入一个代理对象。
  • 等到实际使用 Bean B 的时候,才会去创建真正的实例。
3. 使用 setter 注入或者字段注入

正如前面示例所示,setter 注入和字段注入能够利用 Spring 的三级缓存机制来解决循环依赖问题。

三、循环依赖的检测与调试

1. 查看详细的错误日志

当出现循环依赖时,Spring 会在日志中明确指出循环依赖的路径。

Error creating bean with name 'a': Requested bean is currently in creation: Is there an unresolvable circular reference?
2. 使用 @DependsOn 注解

如果必须要控制 Bean 的创建顺序,可以使用 @DependsOn 注解。不过要谨慎使用,因为它可能会掩盖更深层次的设计问题。 

@Component
@DependsOn("b")
public class A {
    // ...
}

spring自动解决依赖问题请看这篇文章

https://blog.youkuaiyun.com/XiaobaiPlayer/article/details/148286719?spm=1001.2014.3001.5502 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值