Spring循环依赖难道只能通过两个Setter注入解决嘛?

22 篇文章 1 订阅
4 篇文章 0 订阅

Spring循环依赖难道只能通过两个Setter注入解决嘛?

先说结论:并不是,可以是一个setter和一个构造器

如果存在循环依赖的对象关系的话,位置靠上的类会先进行生命周期的加载

所以位置靠上的类必须通过set注入其他属性,这样才不会导致循环依赖的报错

前言

其实想到这个问题是由于网上给出的结论是

于是我便好奇了起来:为什么同样是一个通过Setter注入、一个通过构造器注入,会有两种不同的结果呢?

Setter注入与构造器注入

首先我们先明确哪种是setter注入,哪种是构造器注入

//setter注入
@Autowired
private B b;

//构造器注入
@Autowired
public B(A a) {
    this.a = a;
}

为什么可以一个通过set和一个通过构造器进行注入也不会导致循环依赖的报错

Spring默认在package从上至下加载Bean的生命周期:创建->注入->初始化完成
我们假设代码中,A所在位置在B上方

先构造器注入,再set注入

条件:A是构造器注入,B是set注入

由于A在上方那么会先进行A的生命周期

A在构造器创建实例时,由于容器中B是空的,导致A无法通过构造器创建对象,于是报错

即使为A添加了空参构造器也无济于事,因为使用构造器注入会先行调用有参构造器

先set注入,再构造器注入

条件:A是set注入,B是构造器注入

由于A在上方还是会先进行A的生命周期

此时,由于A有默认的无参构造器直接创建一个空对象放入了三级缓存,为其注入B时,发现容器中B是空的

于是开始B的生命周期,因为在三级缓存中A已经存在,所以B可以直接根据这个对象去通过构造器实例化

实际上是会因为引用了A,为A执行一个提前引用来创建一个动态代理对象放入二级缓存中,然后将二级缓存中A的代理对象给B,这里为了方便理解直接忽略了动态代理这一层缓存

于是B被创建、注入、初始化完成后加入到一级缓存,此时又来到了A的注入阶段,直接将B注入

于是A经过注入与初始化后,也加入到了IOC容器中,至此不会导致报错

所以可以得出结论:并不是只能通过两个Setter注入才能解决循环依赖的问题,也可以是一个setter和一个构造器

如果存在循环依赖的对象关系的话,位置靠上的类会先进行生命周期的加载

所以位置靠上的类必须通过set注入其他属性,这样才不会导致循环依赖的报错

结论依据:

  • 可以通过实现BeanPostProcessor前置调用类的方法将所有Bean依次输出
  • 也可以通过实现BeanNameAware的方法输出Bean的名称

总之我们会发现是B先被初始化完成后才初始化完成了A
所以是先创建了A,然后为其注入B时,启动了B的完整的一个生命周期,才会是B先被初始化完成的这样一个结果

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值