关联知识库:构造器注入和循环依赖
构造器注入和循环依赖
思维路线
- 禁用循环依赖新闻
- 支持循环依赖的历史
- ejb时代背景
- spring的决策,三级缓存的设计思路
- 循环依赖的争议
- 构造器注入的流行
一条旧闻
21年11月,Springboot 2.6.0 默认禁用Bean的循环依赖。
Circular References Prohibited by Default
Circular references between beans are now prohibited by default.
If your application fails to start due to a BeanCurrentlyInCreationException you are strongly encouraged to update your configuration to break the dependency cycle. If you are unable to do so, circular references can be allowed again by setting spring.main.allow-circular-references to true, or using the new setter methods on SpringApplication and SpringApplicationBuilder This will restore 2.5’s behaviour and automatically attempt to break the dependency cycle.默认禁止 Bean 之间的循环引用
如果您的应用程序由于 BeanCurrentlyInCreationException 而启动失败,强烈建议您更新配置以打破依赖循环。如果您无法做到这一点,可以通过将 spring.main.allow-circular-references 设置为 true,或使用 SpringApplication 和 SpringApplicationBuilder 上新的 setter 方法,重新允许循环引用。这将恢复 2.5 的行为并自动尝试打破依赖循环。
From Spring-Boot-2.6-Release-Notes
支持循环依赖的历史原因
️ EJB时代
类之间相互引用产生的循环依赖是一种普遍的编码习惯(即使是在Spring支持循环依赖的当下)。这也说明,循环依赖并非是软件构建中的“硬伤”,而是可商量,可优化的选项。在软件质量要求日益增长的今天,Spring开始对这样“代码坏味道”的土壤出手了。
Spring支持循环依赖的决策因素
- 迁移工作阻力,迁移门槛
- 短期内难以改变的普遍编码习惯
Spring支持循环依赖的决策推演[From Manus].md
- 重量级的EJB与想要解放开发者的Spring
- 无缝迁移与开发者口碑
- “务实”和“灵活”的设计口碑
解决方案: 基于setter注入主流习惯设计了“三级缓存”(单例池/对象引用/bean代理支持)机制。
三级缓存的设计原理分析[From Manus].md
⚠️ 循环依赖的争议
—— 代码高耦合,职责混乱的土壤。
争议历程
-
早期 (2004-2012): “能工作就是好代码”
- 背景: 对抗 EJB 的复杂性,首要任务是让应用能跑起来。
- 争议: 此时争议不大,Spring 的自动解决能力被视为一个强大的“特性”,是其优于 EJB 的证明。
-
中期 (2012-2020): “好代码应该易于测试和维护”
- 背景: 单元测试、代码整洁、SOLID 原则等思想深入人心。
- 争议: 争议最激烈的时期。社区普遍认识到其危害,但框架为了向后兼容依然支持。大量的博客和论坛文章都在辩论和探讨如何“驯服”或“修复”它。
-
现在 (2021-至今): “好代码默认就不该有循环依赖”
- 背景: 云原生、微服务对启动性能和架构清晰度提出更高要求。
- 争议: 争议已基本尘埃落定。随着 Spring Boot 2.6 将其默认禁止,社区和官方的态度已经统一。现在的问题不再是“它好不好”,而是“我该如何重构掉它”。
构造器注入和final的不可变性
循环依赖本质上是一个业务设计问题。 它是由于未能清晰地划分业务边界、未能正确识别核心服务、未能建立单向的业务流程而导致的。
使用构造器注入相当于不再有技术设计容错业务混乱,直接暴露循环依赖问题,强制开发者重新设计业务逻辑关系。
action test 001