建站优化推广,旅游网站营销,集客营销软件官方网站,wordpress 超级卡❤ 作者主页#xff1a;欢迎来到我的技术博客#x1f60e; ❀ 个人介绍#xff1a;大家好#xff0c;本人热衷于Java后端开发#xff0c;欢迎来交流学习哦#xff01;(#xffe3;▽#xffe3;)~* #x1f34a; 如果文章对您有帮助#xff0c;记得关注、点赞、收藏、… ❤ 作者主页欢迎来到我的技术博客 ❀ 个人介绍大家好本人热衷于Java后端开发欢迎来交流学习哦(▽)~* 如果文章对您有帮助记得关注、点赞、收藏、评论⭐️⭐️⭐️ 您的支持将是我创作的动力让我们一起加油进步吧 文章目录 1、什么是循环依赖2、Spring实例Bean的本质3、Spring可以解决哪些情况下的循环依赖4、Spring怎么解决循环依赖5、为什么解决Spring循环依赖需要三级缓存而二级缓存却不行6、总结 1、什么是循环依赖
在Spring框架中循环依赖指的是两个或多个Bean之间相互依赖的情况形成了依赖环路Circular Dependency。换句话说这些Bean之间存在着相互引用导致无法正确地创建和初始化这些 Bean。
通俗来讲就是 Bean A 依赖 Bean B而 Bean B 又依赖于 Bean A或者是 Bean C 依赖自己本身如下图所示 2、Spring实例Bean的本质
在Spring中当实例化一个Bean时会按照依赖关系递归地实例化其所依赖的所有Bean直到某个Bean不再依赖其他Bean或其依赖已经被实例化过。
具体来说当实例化 Bean A 时如果 Bean A 有依赖另一个 Bean BSpring会先实例化 Bean B并将其注入到 Bean A 中。而如果 Bean B 又依赖其他 Bean C那么Spring会先实例化 Bean C并将其注入到 Bean B 中以此类推直到找到一个 Bean 没有依赖其他Bean为止。 3、Spring可以解决哪些情况下的循环依赖
Spring解决循环依赖是由前置条件的
出现循环依赖的Bean必须要是单例(singleton)如果依赖prototype则完全不会有此需求依赖注入的方式不能全是构造器注入的方式
依赖情况依赖注入方式是否解决AB循环依赖AB均采用构造器注入否AB循环依赖AB均采用setter方式注入是AB循环依赖AB均采用属性自动注入是AB循环依赖A中注入的B为setter注入B中注入的A为构造器注入是AB循环依赖B中注入的A为setter注入A中注入的B为构造器注入否
注意 第四种可以而第五种不可以的原因是 Spring 在创建 Bean 时默认会根据自然排序进行创建所以 A 会先于 B 进行创建。 4、Spring怎么解决循环依赖
Spring通过 三级缓存 解决循环依赖
一级缓存 MapString,Object singletonObjects存放完全初始化好的Bean集合二级缓存 MapString,Object earlySingletonObjects存放创建好但没有初始化属性的Bean集合三级缓存 MapString,ObjectFactory? singletonFactories存放正在被创建的Bean的集合
当A、B两个类发生循环依赖时我们看一下Spring是怎么解决循环依赖的
创建A实例实例化的时候把A对象工厂放入三级缓存表示A开始实例化了虽然这个对象还不完整但是先曝出来让大家知道 A注入属性时发现依赖于B此时B还没有创建出来所以先去实例化B。同样的B在注入属性时发现依赖于A它就会从缓存里找A对象。以此从一级缓存到三级缓存去查询A从三级缓存通过对象工厂拿到A发现A虽然不太完善但是却存在于是把A放入二级缓存同时删除三级缓存中的A。此时B已经实例化并且初始化完成把B放入到一级缓存 4. 接着A继续属性赋值顺利从一级缓存中拿到实例化且初始化完成的B对象。此时A对象也创建完成删除二级缓存中的A同时把A放入到一级缓存 5. 最后一级缓存中保存实例化、初始化完成的A、B对象Spring也顺利解决了循环依赖的问题。 注意
因此我们就知道为什么Spring能解决setter注入的循环依赖了因为实例化和属性赋值是分开的所以里面有操作的空间。如果都是构造器注入的话那么都得在实例化这一步完成注入所以自然是无法支持了。 5、为什么解决Spring循环依赖需要三级缓存而二级缓存却不行
Spring框架解决循环依赖的过程中确实使用了三级缓存。这是因为在单纯的二级缓存情况下可能会出现无法解决的循环依赖问题。
二级缓存仅仅可以解决同一个Bean在同一个解析过程中的循环依赖但如果存在多个解析过程二级缓存就无法满足需求。所以Spring引入了三级缓存以便更好地管理和解决多个Bean之间的循环依赖问题。
三级缓存的引入使得Spring可以在不同解析阶段间共享缓存有效地解决了复杂的循环依赖情况确保了Bean的正确初始化。 6、总结
处理循环依赖有多种方式。首先考虑是否能够通过重新设计依赖来避免循环依赖。如果确实不可避免需要循环依赖那么通过上面提到的方式来处理。优先建议使用setter注入来解决。 非常感谢您阅读到这里如果这篇文章对您有帮助希望能留下您的点赞 关注 分享 留言thanks