Spring的循环依赖以及用于处理该情况的三级缓存简单总结

一、Spring的循环依赖问题概述

        指两个或多个 Bean 之间相互依赖,形成一个环形的依赖关系。如下图。

二、三级缓存

2.1 DefaultSingletonBeanRegistry类

2.1.1 Map<String,Object>SingletonObjects

        1.一级缓存"单例池"。

        2.key->beanName value->bean实例。

        3.存放完整生命周期的bean实例。

2.1.2 Map<String,Object>earlySingletonObjects

        1.二级缓存

        2.key->beanName value->bean实例

        3.出现循环依赖的情况下,存放实例化完成的bean实例

2.1.3 Map<String,ObjectFactory<?>>SingletonFactories

        1.三级缓存

        2.key->beanName value->ObjectFactory bean工厂

        3.在出现循环依赖的情况下,用于保存bean创建工厂,以便于创建代理对象

Set<String>singletonsCurrentlyInCreation存储正在创建的单实例bean

解决循环依赖最核心的代码:一二级缓存找不到会去执行三级缓存的lambda表达式,并放入二级缓存Object getSingleton(String beanName,boolean allowEarlyReference)

2.2 AbstractAutoProxyCreator类

Map<Object,Object>earlyProxyReferences

存放着需要提前进行AOP的bean实例的容器

三、为什么设计第二级缓存  、 为什么设计第三级缓存?

3.1 二级缓存(早期曝光对象缓存)

处理循环依赖:可以在一个 Bean 还未完全初始化完成时,先将其早期状态放入该缓存,以便其他依赖它的 Bean 能够获取到并继续初始化流程,从而能够较好地应对一些循环依赖场景。

3.2三级缓存(工厂缓存)

优化性能和资源利用:有些情况下,不必过早地创建实例,通过缓存工厂,可以延迟实例化的时机,避免不必要的资源占用和开销。

更灵活的控制:为处理复杂的依赖关系和初始化过程提供了更精细的控制机制,在特定场景下可以更好地协调 Bean 的创建顺序和状态转换。

四、bean完整的生命周期循环依赖举例

        A创建过程 生命周期

        singletonsCurrentlyInCreation add(A) A是当前正在创建的bean

        1.推断构造方法,实例化 new A() A目标对象->若需提前暴露 Map<a,ObjectFactory>三级缓

        存ObjectFactory(A的bean&beanName&beanDefinition...)

        2.属性注入B->一级缓存查找->没有->创建B

                B创建过程 生命周期

                1.推断构造方法,实例化 new B() B目标对象

                2.属性注入A->一级缓存 没有->sc存在A,出现循环依赖问题->二级缓存 没有->三级缓存

                中查找->ObjectFatory若需AOP则是A代理对象,若不需则是A目标对象->先存入二级缓

                存,再移除三级缓存中的bean->二级缓存中获取A

                3.初始化后,判断是否需要AOP

                4.将完整走完生命周期过程的实例备案,存入singletonObjects“一级缓存”单例池中

                C创建过程 生命周期

                1.推断构造方法,实例化 new C() C目标对象

                2.属性注入A->一级缓存 没有->sc存在A,出现循环依赖问题->二级缓存中获取A

                3.初始化后,判断是否需要AOP

                4.将完整走完生命周期过程的实例备案,存入singletonObjects“一级缓存”单例池中

3.初始化后,判断是否需要AOP(此时判断是否提前进行过AOP,earlyProxyReferences中查找,若有则可以从耳机缓存中查找A代理对象

 4.将完整走完生命周期过程的实例备案,存入singletonObjects“一级缓存”单例池中

singletonsCurrentlyInCreation remove(A)一处已创建完成的A

五、总结

        在 Spring 中,循环依赖是指两个或多个 Bean 之间相互依赖,形成一个环形的依赖关系。Spring 主要通过三级缓存机制来处理循环依赖的情况:一级缓存是已经完全初始化好的 Bean 实例;二级缓存存放早期曝光的 Bean 对象(还未完全初始化完成);三级缓存存放用于创建 Bean 的工厂对象。当遇到循环依赖时,Spring 会利用这些缓存机制来尝试解决,在一定条件下可以成功处理循环依赖,但也存在一些特殊情况可能导致处理循环依赖出现问题,比如构造器注入的循环依赖一般无法解决。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值