高频面试题-说清楚Spring如何解决循环依赖?

这是我参与更文挑战的第2天,活动详情查看: 更文挑战

Spring的循环依赖问题一直是中高级Java高频面试题之一,其中的考点就在于你对Spring中bean的加载过程是否有一定的理解。

那么我们就以下几点说一下。

Spring中常用的注入方式有哪几种?

构造器注入

set方法注入

注解注入

关于这方面的知识之后再细聊,今天重点不是这些。

什么是循环依赖?

循环依赖,注意,这里说的是依赖,而不是调用,这是两个概念,一定不要混淆。

循环依赖从字面意思来看,就是A依赖B,然后B依赖A,当然,这个依赖过程也可以更长,不一定就非要两个互相依赖,十个八个也是循环依赖,只要形成了一个闭环。

如图,这样就形成了一个闭环,简单说,如此依赖下去,就是一个死循环。

如何解决循环依赖?

Spring中的循环依赖包括两种,构造器循环依赖和setter循环依赖。

构造器循环依赖

当使用构造器注入方式时,Spring是无法解决循环依赖的,在出问题时会报错,抛出BeanCurrentlyInCreationException异常。

模拟一下场景的话,大概如下:

1. X1在创建时,发现构造器需要X2类对象,只能去创建X2;

2. X2在创建时,又发现构造器需要X3类对象,只能去创建X3;

3. X3在创建时,又再次发现构造器需要X1对象;周而复始,最终抛出异常。

setter循环依赖

主要来说一下setter循环依赖,通过Spring在创建bean时的一级、二级、三级缓存的概念解决的。

注意:这里解决的只是单例模式下的setter循环依赖,非单例模式下的依然没有办法解决,在业务环境中应当尽量避免此类情况。

创建Bean的缓存概念:

一级缓存:singletonObjects,可以称为成品池,存放完全实例化属性赋值完成的Bean,直接可以使用。

二级缓存:earlySingletonObjects,可以称为半成品池,存放早期Bean的引用,尚未属性装配的Bean

三级缓存:singletonFactories,可以称为工厂池,存放实例化完成的Bean工厂。

通过setter注入时,会经历以下几个过程。

看图说话!

1. X1在创建时,首先根据构造函数创建bean,暴露一个Factory给三级缓存(工厂池),并且将其放入二级缓存(半成品池);然后进行属性的装配,发现有依赖关系,查询三级缓存是否存在,如没有,前往创建。

2. 创建X2时,同X1,前往创建X3。

3. 创建X3时,这时三级缓存中已经存在X1,即可直接注入,然后将X3的bean对象放入一级缓存(成品池)。

4. 随后X2、X1依次可以创建完成,并且放入一级缓存中。

5. 如此就完成setter循环依赖问题的解决,核心就是这个三级缓存。

注意:这里的bean对象创建完成,放入一级缓存中时,会将对应的二级、三级缓存清掉。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Ijiran

一杯咖啡太贵,一块糖就可以

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值