技术面:Spring(循环依赖,spring与springboot的区别)

news/2025/10/22 9:40:01/文章来源:https://www.cnblogs.com/jimoer/p/19157050

Spring的循环依赖

循环依赖是指在使用Spring框架的过程中,两个或多个Bean之间在初始化的过程相互依赖,形成一个依赖闭环,导致容器无法顺利完成Bean的创建和注入,从而可能引发启动失败或运行异常。

@Service
public class ServiceA {@Autowiredprivate ServiceB serviceB;
}@Service
public class ServiceB {@Autowiredprivate ServiceA serviceA;
}

在上面这段代码中:
ServiceA 的实例需要注入 ServiceB 的实例。
ServiceB 的实例又需要注入 ServiceA 的实例。
这就形成了一个 ServiceA → ServiceB → ServiceA 的循环依赖。
当然大于两个的类也可能存在循环依赖,例如:A→ B→ C→ A
image
image

如何解决循环依赖

在Spring中解决循环依赖也是有一定限制的。

  1. 循环依赖的Bean都是单例模式的Bean。
  2. 依赖注入的方式不能都是构造函数注入的方式。

Spring解决循环依赖为什么只支持单例模式的Bean

从本质上来说Spring解决循环依赖的方式是通过提前暴露未初始化完成的Bean来解决循环依赖的,这个尚未初始化完成的Bean是个半成品的Bean,就是未了解决循环依赖才提前放到缓存中的。

在Spring容器中,单例Bean的创建和初始化只会发生一次,而且是在容器启动的时候就完成的。这就说明在整个容器运行期间,单例Bean的依赖关系不会再发生变化,因此可以在容器启动的时候,通过提前暴露半成品的Bean来一次性解决单例Bean循环依赖的问题。
image
而由于原型模式(property)的Bean或Session模型下的Bean,创建和初始化会发生多次,并且是在Spring容器运行期间动态的发生变化,因此提前暴露半成品的Bean并不能解决循环依赖的问题,因为在后续的创建过程中,可能会涉及到多个不同的原型Bean,这就无法像单例Bean那样缓存并复用半成品对象。

所以Spring只能自动解决单例Bean的循环依赖

Spring为什么不支持自动解决构造函数的循环依赖

这个也很好理解,因为在整个Bean的实例化的过程中,是先执行构造函数,只有执行了构造函数后,才算是在堆内存中分配了内存,后面再填充属性,内存地址也不会有变化了。但是如果连构造函数都执行不成功,那这个Bean就连个半成品都不算,所以spring无法解决这种循环依赖。
image
解决这种构造函数的循环依赖有多种方式

  • 重新设计,从代码层面就把循环依赖给杜绝掉,彻底避免循环依赖。
  • 改成非构造函数依赖,可以采用setter注入或属性注入
  • 使用@Lazy注解解决:使用@Lazy注解时,Spring容器会在实际需要该Bean的时候才会进行实例化,而不是在容器启动的时候进行实例化。这样如果两个Bean存在循环依赖,可以使用这种延迟实例化,从而避免在容器启动时触发循环依赖,但并未真正解决循环依赖本身。

Spring三级缓存

Spring三级缓存是什么?

在Spring框架中,BeanFactory是IOC的基础接口,其中DefaultSingletonBeanRegistry类实现了BeanFactory接口,并维护了三个Map,用来做Bean创建时的三级缓存。
image
这三级缓存的介绍

  1. 一级缓存,singletonObjects 单例缓存
    • 类型:ConcurrentHashMap<String, Object>
    • 作用:存放完全初始化完成的单例Bean实例。
    • 说明:这是最终的单例池,所有已经创建并装配好的Bean都会放在这里,供后续直接获取使用。
  2. 二级缓存:earlySingletonObjects
    • 类型:ConcurrentHashMap<String, Object>
    • 作用:存放早期暴露的Bean实例(原始对象,尚未完成属性注入和初始化,半成品)。
    • 当一个Bean正在创建中,但还未完成所有初始化步骤时,可以提前暴露一个“半成品”对象,放入此缓存,供其他Bean引用,从而打破循环依赖。
  3. 三级缓存:singletonFactories
    • 类型:ConcurrentHashMap<String, ObjectFactory<?>>
    • 作用:存放能够创建早期Bean实例的工厂对象(ObjectFactory)。
    • 它并不直接存储Bean实例,而是存储一个lambda或匿名内部类,用于在需要时生成早期暴露的对象。这允许Spring在暴露早期对象的同时,还能应用一些后置处理器(如AOP代理)。

Spring三级缓存是怎么解决循环依赖的?

步骤一:创建Bean-A
  • Spring 启动创建 Bean-A 的流程。在实例化(instantiateBean)之后,属性注入(populateBean)之前,Spring 会将一个 ObjectFactory(工厂)放入 三级缓存 (singletonFactories)。
  • 这个 ObjectFactory 的作用是:当被调用时,可以返回 Bean-A 的一个早期引用(通常是原始对象,或者如果需要AOP,则是一个代理对象)。
步骤二:创建 Bean-A 的依赖 (Bean-B)
  • Spring 开始为 Bean-A 注入属性,发现需要 Bean-B。
  • 检查一级缓存 (singletonObjects),没有找到 Bean-B。
  • 检查二级缓存 (earlySingletonObjects),也没有。
  • 检查三级缓存 (singletonFactories),同样没有 Bean-B。

因此,Spring 开始创建 Bean-B。

步骤三:开始创建 Bean-B
  • Bean-B 被实例化。
  • 同样地,Spring 将一个用于创建 Bean-B 早期引用的 ObjectFactory 放入 三级缓存。
步骤四:创建 Bean-B 的依赖 (Bean-A)
  • Spring 开始为 Bean-B 注入属性,发现需要 Bean-A。
  • 检查一级缓存,没有完整的 Bean-A。检查二级缓存,没有。
  • 检查三级缓存,发现存在 Bean-A 的 ObjectFactory!
  • Spring 调用这个 ObjectFactory.getObject() 方法。
  • ObjectFactory 执行其逻辑(通常会调用 getEarlyBeanReference()),返回 Bean-A 的一个早期引用。
  • 这个早期引用被放入 二级缓存 (earlySingletonObjects),同时从三级缓存中移除对应的工厂。
  • Spring 将这个早期引用的 Bean-A 注入到 Bean-B 中。
步骤五:完成 Bean-B 的创建
  • Bean-B 完成属性注入和初始化。
  • 完全初始化好的 Bean-B 被放入 一级缓存 (singletonObjects)。
  • 从二级缓存中移除 Bean-B 的早期引用。
步骤六:回到 Bean-A 的创建
  • 现在 Bean-B 已经创建完毕并放入一级缓存。
  • Spring 继续为 Bean-A 注入属性,需要 Bean-B。
  • 直接从 一级缓存 中获取到完整的 Bean-B,注入到 Bean-A 中。
  • Bean-A 完成后续的初始化流程。
  • 完全初始化好的 Bean-A 被放入 一级缓存 (singletonObjects)。
  • 此时,Bean-A 和 Bean-B 都已创建完毕,循环依赖成功解决。

解决循环依赖一定要三级缓存吗?

其实理论上,一级加二级缓存就可以解决简单场景的单例Bean的循环依赖,但是三级缓存的设计还涉及到更丰富场景的支持,例如:支持AOP(动态代理)的代理对象的提前暴露。

如果只有二级缓存:在 Bean-A 实例化后,直接将其原始对象放入二级缓存。当 Bean-B 需要时,直接从二级缓存拿到原始的 Bean-A。

如果 Bean-A 需要被 AOP 代理(例如添加事务),那么最终放入一级缓存的应该是 代理对象,而不是原始对象。

但如果二级缓存里已经存了原始对象,那么 Bean-B 拿到的就是原始对象,这就导致了 不一致性:Bean-B 持有的是原始对象,而其他地方(一级缓存)持有的是代理对象

即便没有 AOP,三级缓存的设计也有其必要性。它通过 ObjectFactory 延迟暴露早期引用,确保 Spring 可以在需要时介入生成代理或执行后置处理器,而不仅仅是直接返回原始对象。

Spring默认支持循环依赖吗

这个是看具体版本而言的,在SpringBoot2.6之前是默认支持循环依赖的,但是从Spring Boot 仍支持循环依赖,但变为可配置项,且默认关闭,也就是说从SpringBoot2.6以后是默认不支持循环依赖的,如果启动时存在循环依赖,这个配置未打开,是会报错的。

虽然默认不再支持循环依赖,但是我们可以通过以下方式开启对循环依赖的支持。

  1. 在配置文件中加入此配置spring.main.allow-circular-references=true
  2. @Lazy注解,在@Autoired地方增加即可。

Spring 团队已明确表示 未来可能彻底移除循环依赖支持,建议开发者避免依赖此机制

Spring和SpringBoot的区别

Spring 和 SpringBoot 是 Java 生态中非常重要的两个框架,它们密切相关,但定位和目标不同。
简单来说,Spring 是一个功能强大的基础框架,而 SpringBoot 是建立在 Spring 之上的“脚手架”工具,旨在简化 Spring 应用的开发和部署。

以下几点是SpringBoot在Spring的基础上做的最主要的几点来提升开发效率与降低开发成本:

  1. 自动配置,SpringBoot通过Auto-Configuration来减少开发人员的配置工作。可以通过引入一个 starter 一次性引入所需的所有依赖,使开发人员可以更专注于业务逻辑而不是配置。
  2. 内嵌Web服务器,SpringBoot内置了常见的Web服务器(如Tomcat、Jetty),这意味着您可以轻松创建可运行的独立应用程序,而无需外部Web服务器。
  3. 约定大于配置,SpringBoot中有很多约定大于配置的思想的体现,通过一种约定的方式,来降低开发人员的配置工作。如他默认读取spring.factories来加载starter、读取application.propertiesapplication.yml文件来进行属性配置等。

更详细的区别

特性 Spring SpringBoot
核心定位 一个全面的、基础的 Java 框架,提供企业级应用开发的核心功能(如依赖注入、面向切面编程) Spring 框架的扩展,专注于简化 Spring 应用的开发和配置,实现"开箱即用"
配置方式 需要大量手动配置(XML 或 Java 配置类),例如:
- 配置数据源
- 配置 MVC 分发器
- 配置事务管理
通过自动配置(Auto-Configuration)机制,根据 classpath 中的依赖自动配置应用,只需少量配置(如 application.properties
依赖管理 需要手动管理所有 Spring 模块(如 spring-core, spring-webmvc)和其他第三方库的版本,容易出现版本冲突 通过起步依赖(Starter Dependencies)简化依赖管理:
- 例如 spring-boot-starter-web 自动引入 Spring MVC、Tomcat 等所有必要依赖
- Spring Boot 的父 POM 管理了所有依赖版本,确保兼容性
内嵌服务器 传统 Spring 应用需要将应用打包成 WAR 文件,部署到外部 Servlet 容器(如 Tomcat、Jetty) 内置了 TomcatJettyUndertow 等 Web 服务器,应用可打包成可执行 JAR 文件,通过 java -jar 直接运行
开发效率 需要大量基础配置工作,初始搭建速度较慢 极大提高开发效率,开发者可以专注于业务逻辑,无需关注基础配置
监控与管理 需要自行集成健康检查、指标收集等功能 通过 Spring Boot Actuator 提供开箱即用的生产级监控功能:
- 健康检查(health
- 指标收集(metrics
- 外部化配置(configprops
- 环境信息(env
适用场景 适合需要高度定制化、复杂配置的大型企业级应用 适合快速开发微服务、RESTful API、需要快速迭代的中小型项目,是构建现代云原生应用的首选

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/943048.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

CI_CD前端发布增加cnpm编译失败跳出不部署的逻辑

原创CI/CD前端发布增加cnpm编译失败跳出不部署的逻辑Jenkins Pipeline中添加编译失败终止部署的逻辑,以下是修改建议: stage(代码编译){when { environment name: deploy_env, value: deploy }steps {script {try {s…

2025年GEO品牌推荐榜单:云视GEO领跑行业的技术解析

文章摘要 本文深入解析2025年GEO领域的品牌推荐榜单,重点介绍四川云视有客科技有限公司的云视GEO技术优势。基于GEO-AI搜索优化和线性规划算法,云视GEO实现干预延迟≤0.3秒、效率提升1000倍,并获国家工信部认证,帮…

confluence8

原创confluence8.5配置openldap配置 LDAP 用户目录 1、服务器设置2、LDAP模式3、LDAP权限4、高级设置5、用户模式设置6、组模式设置7、成员模式设置

2025年10月长白山度假酒店推荐:性价比与景观体验排行

十月的长白山进入一年中最绚烂的秋色时段,霜染红叶与初雪交织,摄影爱好者、亲子家庭、自驾车队、企业团建四面涌来,核心诉求高度一致:在景区车程半小时内找到“住得安心、吃得地道、拍得出片”的落脚点。过去三年,…

基于分类器AUC的无模型变点检测技术

本文提出了一种创新的无模型变点检测方法,利用分类器的AUC指标构建检验统计量。该方法无需对数据结构做严格假设,适用于非平稳复杂数据集,通过理论分析和实验验证展现了优于现有方法的性能。基于分类器AUC的无模型变…

2025 年最新推荐!景观石厂家推荐排行榜,涵盖千层石 / 泰山石 / 鹅卵石等多品类,全方位解析优质品牌助您精准选择

引言 当前园林景观行业飞速发展,景观石作为核心元素需求激增,但行业乱象却让消费者选品困难重重。部分企业过度开采致优质资源枯竭、破坏环境,产品同质化严重缺乏创新,技术不足难满足个性化需求,低价恶性竞争还扰…

2025年除尘设备厂家权威推荐榜单:除尘器/脉冲除尘器/中央脉冲除尘器/工业除尘器源头企业综合评测与选购指南

2025年除尘设备厂家权威推荐榜单:除尘器/脉冲除尘器/中央脉冲除尘器/工业除尘器源头企业综合评测与选购指南 随着环保政策的持续收紧和工业绿色转型的加速推进,除尘设备行业正迎来新一轮技术革新与市场洗牌。作为工业…

2025 年高强钢板厂家最新推荐排行榜:涵盖宝武 / 合金 / Q550D 等热门型号,优质企业综合实力甄选

引言 当前高强钢板市场需求旺盛,但行业乱象凸显:部分产品耐磨性差、强度与韧性失衡,导致设备损耗快、维护成本高;供应商资质混杂,产品规格混乱,多数企业缺乏定制化服务能力,难以满足矿山、冶金、化工等不同行业…

2025 年注浆管厂家最新推荐榜:聚焦桩基 / 钢花 / 管棚 / 隧道 / 预埋等多场景需求,精选优质厂家助力工程高效采购

引言 当前地下工程、地基加固等基建领域持续扩张,注浆管作为保障工程质量与安全的核心材料,市场需求激增,但行业乱象也随之凸显。众多品牌混杂导致产品质量参差不齐,部分厂家忽视原材料甄选与工艺把控,产出的注浆…

2025年10月中国AI关键词排名优化公司排行:五强实测评价

正在考虑“AI关键词排名优化”的企业,大多面临同一组难题:传统SEO流量见顶,DeepSeek、豆包、Kimi等AI对话平台却每天新增千万级提问,品牌若不能在生成式回答里被点名,就等于把订单拱手让人。2025年三季度工信部《…

2025年CNAS认证咨询公司推荐:权威指南,全方位服务解析

在2025年检验检测行业高速发展的当下,CNAS(中国合格评定国家认可委员会)认可已成为实验室提升技术能力、管理水平和国际互认度的关键标志。根据ISO/IEC 17025等标准,CNAS认证不仅帮助机构减少质量风险、增强市场竞…

CRM沦为摆设?纷享销客系统运营分析功能助力企业提升数字化效能

当企业数字化进入深水区,越来越多企业将营、销、服全业务搬上 CRM ,希望依靠系统管理实现业务提效增长。可实际却常陷入“业务上系统,效果看不见”的困境:员工抱怨系统难用却讲不清卡点;促销活动发布却不知道经销…

2025年10月GEO优化服务商推荐:全平台同步优化排行榜

引言与现状分析 当品牌发现传统SEO在AI搜索场景下曝光骤降、不同平台结果差异巨大时,GEO(生成式引擎优化)成为新刚需。2025年国内月活过亿的DeepSeek、豆包、通义千问、元宝、Kimi五强并存,算法周级迭代,企业若仅…

2025年10月中国AI关键词排名优化公司推荐榜:五家对比与实测排名

当企业发现客户在豆包、DeepSeek、Kimi里问“哪家公司好”时,跳出的答案却找不到自己,焦虑便随之而来。2025年生成式AI日均调用量已突破8亿次,传统SEO流量被快速分流,AI关键词排名优化(GEO)成为新战场。财政部《…

2025年太阳能板品牌综合排名TOP10:深圳精益太阳能板领跑行业

摘要 太阳能板行业在2025年迎来技术爆发期,转换效率和可靠性成为竞争核心。本文基于市场调研和用户反馈,为您呈现前十名太阳能板品牌排名,并提供详细对比,助您快速选择优质供应商。排名表单供参考,旨在帮助企业决…

2025年太阳能板品牌综合实力排行榜TOP10:深圳精益太阳能板领跑行业

摘要 随着全球能源转型加速,太阳能板行业在2025年迎来技术突破与市场爆发期。行业数据显示,光伏发电成本较五年前下降47%,转换效率平均提升至22.5%以上。本文基于技术参数、市场口碑、产能规模等维度,对全国太阳能…

2025年中国国际健康营养博览会(NHNE):权威深度解析亚洲旗舰展的供需新秩序

引言 本文从“供需对接效率”这一核心维度出发,为健康营养产业链上下游企业、投资机构及政策研究者提供一份可量化的客观参考,避免泛泛而谈。 背景与概况 2025年11月19-21日,NHNE中国国际健康营养博览会将在南京国际…

2025 年铝板厂家最新推荐榜:聚焦优质铝板企业,为工业与建筑采购提供专业参考1100/3003/3004/5052/5083/ 6061铝板厂家推荐

引言 随着工业制造与建筑装饰行业的高速发展,铝板作为核心材料,市场需求持续增长,但行业内品牌繁杂、产品质量差异显著的问题也愈发突出。部分品牌存在原材料把控不严、生产工艺落后导致产品性能不达标,以及售后响…

Ubuntu更新积压:短暂Canonical中断如何引发多日延迟

2025年9月,Canonical服务器仅36分钟的中断导致Ubuntu更新系统出现多日延迟。本文深入分析集中式仓库架构的脆弱性、镜像同步延迟的连锁反应,以及用户应对策略,揭示了分布式系统设计中关键的基础设施问题。Ubuntu更新…

2025 年不锈钢板厂家最新推荐榜:精选优质 304/316L/310S 等材质厂家,助力企业高效采购规避劣质产品

引言 当前不锈钢板市场乱象频发,部分厂家用劣质坯料生产,导致产品耐腐蚀性、强度不达标,无法满足建筑装饰、机械设备等领域需求;供应商服务水平参差不齐,缺乏专业技术团队,供货周期不稳定,严重影响下游企业生产…