这里是小奏,觉得文章不错可以关注公众号小奏技术
背景
不知道多少入门spring
or spring boot
的小伙伴
对spring
如何解决循环引用一定是不陌生的,什么三级缓存啥的。
包括自己 多年前还看一些培训视频去整理这块内容。
现在自己看也看不懂哈哈
如果要问为什么会这么多人去了解这个复杂但是没用的东西呢?
没用主要是我主观认为
其实主要还是各种培训机构+营销号的推送。
比如有很多这样的标题
- 面试官:SpringBoot 循环依赖,如何解决?
- 想进阿里?先搞懂Spring Bean的循环依赖
等等
当然也有面试可能会问,那面试官会问是不是也是受这些培训机构和营销号影响呢
时至今日仍然有许多人在继续研究
如果我们打开搜索引擎,限制时间范围的搜索,会发现,即使限制时间到一年内
搜索spring 循环
关键词
仍然能发现大量文章在讲解这个复杂但没什么用的问题
spring boot何时禁止的循环引用
早在2021
年8月13号,spring boot
创始人wilkinsona
就已经提出了要在spring boot
禁用循环引用
随后wilkinsona
大神就向spring-framework
社区提交了该issue
在 Spring Boot 2.6 中,我们打算默认禁止循环引用,并通过配置属性和 Java API 重新开启循环引用。作为其中的一部分,我想更新我们的 BeanCurrentlyInCreationFailureAnalyzer,建议在万不得已的情况下,再次开启循环引用,以打破循环。只有当 AbstractAutowireCapableBeanFactory.allowCircularReferences
为 false 时,我才会建议这样做。遗憾的是,如果不使用反射,我就无法获取标志的值。能否添加一个访问器?
随后spring
也马上通过pr进行了支持
- pr链接
如果2.6之后的版本要允许循环引用必须手动配置
spring:
main:
allow-circular-references:true
bean的循环引用算设计缺陷吗
实际我们从wilkinsona
大神中的描述来看,我们可以看到循环引用本身就不应该被允许,默认就应该禁止。
使用循环引用并没有什么好处,所以在2021
就已经被禁用的循环引用。
时至今日2024年5月,这个问题的还能频繁出现在各大博客平台
可能还会有面试官会去问这个问题(没调研)
不知道想考察候选人的什么能力,或者说知道了这个问题能解决什么问题?
官方都不推荐这么做
golang从编译层面禁止循环引用
如果熟悉golang的同学会发现,这种新兴语言在语言设计的时候就直接禁用了循环用。 如果两个包比如 a、b相互引用就会直接运行报错
import cycle not allowed
并且没有开关可以支持
实际在golang官方也有提出类似的问题想要支持循环引用
参考
- 翻译
我知道,不允许导入循环是goalng
设计的初衷。 但是,解决导入循环问题让我很沮丧。 而且,编写两个相互依赖的耦合组件非常容易
虽然我们可以使用接口来解决这个问题,但它会降低可读性,因为开发人员必须仔细阅读源代码才能找出接口所代表的实例(滥用接口)。 有许多 Go 标准软件包依赖于运行时私有调用,并使用 go:linkname 来解决导入循环问题。不过,这仍然是一种黑客行为,Go 团队并不推荐使用。 我相信很多人在遇到导入周期问题时都会花时间重构代码,这固然是好事,但在业务逻辑开发中,这有时是不可原谅的。
担忧:引入依赖性分析会牺牲多少编译时间?是否有最新的研究进展可以集成快速依赖性分析?
随后官方也给出了自己的理解
Go语言不允许导入循环迫使程序员更多地考虑他们的依赖关系,并保持依赖图清晰和构建速度快。相反,允许循环会导致懒惰、糟糕的依赖管理和缓慢的构建。最终,人们会以一个包含整个依赖图的单一循环块结束,迫使它变成一个单一的构建对象。这对构建性能和依赖解析非常不利。这些块也需要比一开始保持图为一个合适的有向无环图(DAG)所需的工作量更多的努力来解开。
在这一点上,前期的简单性是值得的。
导入循环可能很方便,但其代价可能是灾难性的。它们应该继续被禁止
简单来说就是为了构建性能和保持包的依赖关系简单清晰
总结
可以看到循环引用的发展历程,我们会发现一些框架和语言慢慢从设计层面想要禁用循环引用
所以设计本身的不合理,为什么还要继续去深入了解这种不合理的需求的实现呢?
知道背后的原理到底是为什么解决什么问题呢?
还是说就是想单纯为了卷而卷? 不为解决问题,就是觉得这个问题复杂,可以考验候选人?实际复杂有意义的问题不知道有多少
与其用循环引用这种不太有意义的问题我倒是觉得还不如换成更实际的问题