首页 > 其他分享 >Spring 的循环依赖

Spring 的循环依赖

时间:2024-09-18 10:50:57浏览次数:11  
标签:缓存 Spring 循环 代理 Bean 依赖 三级

在 Spring 中,循环依赖是指两个或多个 Bean 相互依赖,导致在创建过程中出现了依赖死锁的问题。为了解决循环依赖,Spring 引入了三级缓存机制。了解为什么需要三级缓存机制,首先要明白循环依赖是如何发生的,以及两级缓存为什么不足够。

一、循环依赖是什么?

假设有两个 Bean AB

  • A 依赖于 B
  • B 依赖于 A

如果没有缓存机制,Spring 在创建 A 时会发现它需要 B,于是去创建 B,但在创建 B 时又发现需要 A,这时就会产生循环依赖,最终导致栈溢出或抛出异常。

二、三级缓存机制

Spring 使用三级缓存(三级依赖处理机制)来解决循环依赖问题,分别是:

  1. 一级缓存singletonObjects,用于存储完全初始化好的单例对象。

    • 完全初始化后的 Bean 会放入一级缓存中,表示该 Bean 已经准备好可以使用了。
  2. 二级缓存earlySingletonObjects,用于存储提前暴露的 Bean,主要是尚未完成依赖注入但已经实例化的 Bean。

    • 这个缓存用于提前暴露尚未完成初始化的 Bean,防止循环依赖无法解决。通常情况下,如果某个 Bean 已经实例化但还没有完成后续的属性填充等操作,它会存放在这个缓存中。
  3. 三级缓存singletonFactories,用于存储 Bean 的 ObjectFactory(对象工厂),这个工厂提供对该 Bean 的代理对象(比如 AOP 代理对象)的创建逻辑。

    • 三级缓存的存在使得 Spring 可以在 Bean 创建的早期阶段将未完全初始化的 Bean 提供出来,尤其是代理对象。这样即使 Bean 还没有完成依赖注入,也能通过工厂获得它的一个早期引用。

三、为什么需要三级缓存?两级不行吗?

假如只使用一级缓存和二级缓存:

  • 一级缓存只存储已经完全初始化好的 Bean,显然无法解决循环依赖问题,因为 Bean 尚未完成初始化时无法放入一级缓存。
  • 二级缓存则存储提前暴露的 Bean,但这通常是直接的原始对象,而不是代理对象。如果应用了 AOP 或者需要创建代理对象的场景中,依赖的 Bean 如果在循环依赖中被提前暴露时,可能无法应用正确的代理。

三级缓存 允许通过 ObjectFactory 这种延迟加载的方式,在需要的时候创建早期引用,包括创建代理对象。这确保了即使在循环依赖中,Spring 也可以在合适的时间点创建完整的代理对象,而不是仅仅提供原始对象。

四、总结

三级缓存机制的关键点在于:

  • 二级缓存不能解决 Bean 代理的问题,特别是在涉及到 AOP 的情况下。
  • 三级缓存通过引入 ObjectFactory,可以确保在代理场景下也能处理循环依赖,提前暴露还未完全初始化的代理对象。

因此,两级缓存不足以解决所有循环依赖问题,特别是在涉及到代理对象的情况下,三级缓存的机制显得非常必要。

4o

标签:缓存,Spring,循环,代理,Bean,依赖,三级
From: https://blog.csdn.net/m0_68570169/article/details/142309113

相关文章

  • Springboot在线问卷调查系统-计算机毕业设计源码12500
    摘要随着信息技术在管理上越来越深入而广泛的应用,管理信息系统的实施在技术上已逐步成熟。本文介绍了在线问卷调查系统的开发全过程。通过分析在线问卷调查系统管理的不足,创建了一个计算机管理在线问卷调查系统的方案。文章介绍了在线问卷调查系统的系统分析部分,包括可行性分......
  • springboot家校共育平台-计算机毕业设计源码54235
    摘 要采用高效的SpringBoot框架,家校共育平台为家长与教师提供了便捷的沟通渠道。该平台整合了丰富的教育资源,实现了家校之间的即时信息互通,从而助力协同教育。为进一步方便用户访问和使用,平台与微信小程序进行了深度整合。家长和教师现在可以通过微信小程序轻松访问平台,无......
  • [附源码]超简洁个人博客网站搭建+SpringBoot+Vue前后端分离
    今天带来一款优秀的项目:个人博客系统源码 。系统采用的流行的前后端分离结构,内含功能包括"写博客文章",“修改博客文章”,“富文本编辑器”,“评论管理”“管理员角色”,“游客角色”,“文章标签”,“文章分类”如果您有任何问题,也请联系小编,小编是经验丰富的程序员! 一.系统演......
  • Spring Cloud全解析:服务调用之自定义Feign的配置
    自定义Feign的配置Feign的默认配置类是FeignClientsConfiguration,其内部定义了Feign默认使用的编码器、解码器、契约、重试机制等@Bean@ConditionalOnMissingBeanpublicDecoderfeignDecoder(){//解码器,将字节数组反序列化为方法返回值类型的对象,默认只支持反序列化为St......
  • JavaScript 中循环数据、改变数据的几种方法
    将数组对象中的属性值取出并组成新的数组letarr=[{name:"张三",age:"1",sex:"男",grade:11},{name:"李四",age:"2",sex:"男",grade:12},{name:"王五",age:"3",sex:"男",gra......
  • springboot贵州特色产品销售管理系统-计算机毕业设计源码80943
    摘 要随着信息技术的快速发展和电子商务的广泛应用,传统的销售管理模式已经难以满足现代企业的需求。特别是在贵州这样一个充满特色产品的地区,如何有效地推广和销售当地特色产品,成为了一个亟待解决的问题。为此,开发一套基于SpringBoot+Vue的贵州特色产品销售管理系统,不仅可以......
  • springboot二手书交易系统-计算机毕业设计源码81264
    目录1绪论1.1选题背景与意义1.2国内外研究现状1.3论文结构与章节安排2系统分析2.1可行性分析2.2 系统功能分析2.2.1功能性分析2.2.2非功能性分析2.3 系统用例分析2.4 系统流程分析2.4.1 数据流程2.4.2 业务流程2.5本章小结3 系统总体......
  • 基于Springboot的大学社团管理平台的设计与实现(源码+LW+调试文档)
     目录:程序功能截图:程序部分代码参考:数据库sql:程序技术介绍:后端springboot介绍:mysql介绍:程序论文:​选择我的理由:程序获取:......
  • 基于SpringBoot的大学志愿活动管理系统的设计与实现(源码+LW+调试文档)
     目录:程序功能截图:程序部分代码参考:数据库sql:程序技术介绍:后端springboot介绍:mysql介绍:程序论文:​选择我的理由:程序获取:......
  • SpringBoot 如何利用异步接口,提高系统吞吐量
    一、前言Servlet3.0之前:每一次Http请求都由一个线程从头到尾处理。Servlet3.0之后,提供了异步处理请求:可以先释放容器分配给请求的线程与相关资源,减轻系统负担,从而增加服务的吞吐量。在springboot应用中,可以有4种方式实现异步接口:AsyncContextCallableWebAsyncTaskDeferredResult......