Java Spring boot解决循环依赖的问题
循环依赖问题
通过将自己注入自己,使用代理对象调用add方法解决了事务失效问题,但是有些同学有疑问,这样不会产生循环依赖吗?
什么是循环依赖
在 Spring 中,如果一个 bean 尝试将自身引用注入到自身中,通常会引发循环依赖。
首先搞清楚什么是循环依赖:
两个Bean,A依赖B,B依赖A就构成了循环依赖,如下图:
同样的道理,如果在A中注入A表示A依赖A,也就构成了循环依赖。
Spring 如何解决循环依赖
以上图为例说明Spring是如何处理循环依赖问题的?
首先按照常规的流程是:
创建A实例–》初始化A–》注入B–》创建B实例–》初始化B–》注入A
在初始化A时需要注入B,要注入B就需要创建B实例再初始化B,而在初始B时需要注入A,此时A还没有创建完成就陷入死循环。
针对循环依赖的问题Spring会上边的过程调整为下边的流程:
创建A实例–》创建B实例–》在B中注入A–》B初始化—》在A中注入B–》A初始化。
Spring是如何做到呢?
Spring会延迟初始化,B需要注入A,此时Spring会先实例化A,把一个半成品A注入给B,延迟A的初始化。
循环依赖的底层原理是Spring通过三级缓存实现:
1)singletonObjects缓存:这是 Spring 容器用来缓存完全初始化好的单例 bean 实例的缓存。当一个 bean 初始化完成后,它会被放入singletonObjects缓存中。这个缓存是单例 bean 的最终缓存,也是 BeanFactory 中保存 bean 的主要缓存。
2)earlySingletonObjects缓存:这个缓存是用来保存被实例化但还未完全初始化的 bean 的引用。当一个 bean 已经被实例化(但还未初始化)时,它会被放入earlySingletonObjects缓存中。
3)singletonFactories缓存:这个缓存保存的是用于创建 bean 实例的 ObjectFactory,用于支持循环依赖的延迟初始化。当一个 bean 被实例化,但尚未完全初始化时,Spring 会在singletonFactories缓存中查找该 bean 的ObjectFactory。这个ObjectFactory会在需要时被调用来完成 bean 的初始化。
Spring 通过这三级缓存的组合,来确保在循环依赖情况下,能够正常初始化 bean。当两个或多个 bean 之间存在循环依赖时,Spring 使用 singletonFactories 缓存来存储 bean 的对应工厂(ObjectFactory)。当一个 bean 在初始化过程中需要依赖另一个还未初始化的 bean 时,Spring 会调用相应的 ObjectFactory 来获取对应的 bean 实例,这样就实现了循环依赖的延迟初始化。一旦 bean 初始化完成,它就会被移动到singletonObjects缓存中。
举例:
创建A实例–》创建B实例–》在B中注入A–》B初始化—》在A中注入B–》A初始化。
创建A实例(半成品),在earlySingletonObjects放入A半成品。
创建B实例(半成品),在earlySingletonObjects放入B半成品。
在B中注入A,通过singletonFactories拿到A的对象工厂,通过对象工厂拿到A的半成品注入到B中。
B初始化完成,将B从earlySingletonObjects移动到singletonObjects。
A初始化完成,将A从earlySingletonObjects移动到singletonObjects。
1. 本站所有资源来源于用户上传和网络,如有侵权请邮件联系站长!
2. 分享目的仅供大家学习和交流,您必须在下载后24小时内删除!
3. 不得使用于非法商业用途,不得违反国家法律。否则后果自负!
4. 本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解!
5. 如有链接无法下载、失效或广告,请联系管理员处理!
6. 如遇到加密压缩包,请使用WINRAR解压,如遇到无法解压的请联系管理员!
7. 本站有不少源码未能详细测试(解密),不能分辨部分源码是病毒还是误报,所以没有进行任何修改,大家使用前请进行甄别!
66源码网 » Java Spring boot解决循环依赖的问题