什么是循环依赖?如何解决spring循环依赖问题?

(面试的时候可能会被问到哟!!!!!!!)

1.定义

        循环依赖就是循环引用,就是两个或者两个以上的bean对象互相持有对方,最终形成闭环。

比如:A依赖B,B又依赖C,C又依赖A,形成循环依赖。

2.出现的场景

     构造器的循环依赖

     field属性循环依赖

3.如何检测循环依赖

        在创建bean的时候可以给该bean打个标签,如果递归调用回来发现bean正在创建的话,就表示发生了循环依赖。

4.如何解决循环依赖

Spring内部通过三级缓存来解决循环依赖的问题。

所谓三级缓存,就是spring容器解决循环依赖的三个map:

一级缓存:singletonObjects,是一个ConcurrentHashMap,也叫单列池,存放已经经历了完整生命周期的Bean对象;

二级缓存:earlySingletonObjects,是一个HashMap,存放早期暴露出来的Bean对象,Bean的生命周期未结束,属性还未填充完整;

三级缓存:singletonFactories,第三级缓存value是一个工厂,三级缓存存放可以生成bean的工厂。

注意:

只有单例的Bean会通过三级缓存来解决循环依赖的问题,而非单例的Bean,每次从容器获取都是一个新的对象,都会重新创建,所以非单例的Bean是没有缓存的,不会放在三级缓存中。

整个流程大致如下:
1. 首先 A 完成初始化第一步并将自己 提前曝光 出来(通过 ObjectFactory 将自己提前曝光),在
初始化的时候,发现自己依赖对象 B ,此时就会去尝试 get(B) ,这个时候发现 B 还没有被创建
出来;
2. 然后 B 就走创建流程,在 B 初始化的时候,同样发现自己依赖 C C 也没有被创建出来;
3. 这个时候 C 又开始初始化进程,但是在初始化的过程中发现自己依赖 A ,于是尝试 get(A) 。这
个时候由于 A 已经添加至缓存中(一般都是添加至三级缓存 singletonFactories ),通过 ObjectFactory 提前曝光,所以可以通过 ObjectFactory#getObject() 方法来拿到 A 对象。 C
A 对象后顺利完成初始化,然后将自己添加到一级缓存中;
4. 回到 B B 也可以拿到 C 对象,完成初始化, A 可以顺利拿到 B 完成初始化。到这里整个链路
就已经完成了初始化过程了。
关键字:三级缓存,提前暴露
  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值