如何通过三级缓存解决 Spring 循环依赖
我们非常重视原创文章,为尊重知识产权并避免潜在的版权问题,我们在此提供文章的摘要供您初步了解。如果您想要查阅更为详尽的内容,访问作者的公众号页面获取完整文章。
本文讨论了Spring中循环依赖的问题,并介绍了Spring容器是如何解决这一问题的。作者计划通过几篇文章来详细说明这个高频面试题,并先从设计思路而非源码角度去探讨循环依赖的解决方案。
1. 循环依赖
1.1 什么是循环依赖
循环依赖是指两个Bean互相依赖,如AService和BService相互持有对方的引用,这是一种常见的循环依赖类型。此外,还有三者之间的循环依赖以及自我依赖的情况。代码设计应避免循环依赖,但Spring可以处理大部分情况。
1.2 循环依赖的类型
循环依赖有三种形态:两个Bean相互依赖、三者相互依赖以及自我依赖。Spring框架默认处理循环依赖,但在最新版中需要显式配置才能启用该功能。
2. 循环依赖解决思路
2.1 解决思路
Spring通过在容器中使用缓存池来解决循环依赖问题。它首先创建一个原始Bean,暂存到缓存池中,然后解析依赖并赋值。在依赖处理过程中,如果出现循环依赖,将使用缓存池中的原始Bean。Java的引用传递机制保证了即使是原始Bean的引用,最终也会指向完整的Bean。Spring的缓存包括三级缓存:singletonObjects、earlySingletonObjects和singletonFactories,它们分别用于存储完整Bean、原始Bean和Bean的工厂。
2.2 存在AOP怎么办
当涉及到AOP,Spring使用三级缓存中的singletonFactories来解决代理对象的创建问题。在创建Bean的过程中,如果检测到Bean需要代理,则利用三级缓存中的Lambda表达式提前生成代理对象,以保证即使发生循环依赖,也能获取到正确的代理对象。
3. 小结
Spring解决循环依赖的关键在于提前暴露对象和提前执行AOP处理。通过这两个机制,即使在Bean属性赋值前发生了循环依赖,Spring也能保证最终获得的是完整的、正确代理的Bean。然而,三级缓存并不是万能的,对于某些情况可能无法解决循环依赖。
本文最后提到,作者将在后续文章中从源码角度验证本文的内容,并深入探讨无法解决的循环依赖情形。
此外,文章开头提到了TienChin项目的视频杀青,它使用Spring Boot和Vue3技术栈,邀请读者加入完成超过90%的项目。
想要了解更多内容?