Spring-循环依赖是如何解决的

1、bean被创建保存到spring容器的过程

1、实例化 -> 获取对象;

2、填充属性;这里可能需要依赖其它的bean。

3、AOP代理对象替换;

4、加入单例池;

问题:

循环依赖怎么处理

ServiceA 中有属性ServiceB b;

ServiceB中有属性ServerA a;

如何打破循环?

在第1步中,aService实例化后存入到map中。在2.2步中,如果单例池中没有,再去查前面的map。这样就打破了无限循环逻辑。

如果循环依赖中的bean是需要做AOP替换的代理对象,问题又该如何解决?

需要提前进行AOP创建代理对象-早期对象。

2、spring容器启动过程中用到的三个map

1、单例池 singletoneObjects,存储完整的bean实例;

2、早期的单例池 earlySingletonObjects,用于解决AOP代理对象的问题;确保创建过程中的不完整的对象也是单例的。

3、singletonFactories,value是一个Function。

如果没有三级缓存singletonFactories,那么在创建AOP代理对象时就无法获取到原目标target普通对象。如果可以获取到到target对象,那么循环就会被打破,循环问题就解决了。

所以singletonFactories中的value其实是一个获取早期对象的函数,里面可能返回普通对象也可能返回AOP对象,但都是没有执行完完整实例化过程的对象(早期对象),这里设计比较巧妙。

3、为什么不先实例化所有的bean,再进行属性依赖注入?

Spring 容器在启动时不会立即实例化所有的 bean,因为这样做可能会创建许多不会被用到的 bean 实例,从而浪费内存和初始化时间。相反,Spring 容器按需创建 bean,即当应用程序请求一个 bean 时,容器才会创建它,并且如果该 bean 依赖其他 bean,则先实例化依赖的 bean。

这种懒加载(Lazy Loading)的策略使得容器更加高效,因为它只实例化必需的组件,从而节省资源。

也会存在构造注入的场景,所以这时也是先需要其它bean实例的。

3、哪些场景下Spring还是会报循环依赖的错误?

1、@Async + 循环依赖 。

解决:-> 添加@Lazy

2、循环依赖&唯一构造注入

根本无法实例化!因为构造函数中的逻辑循环了!

解决:改成属性注入而非构造!

学习资料参考:

3、什么是二级缓存,它的作用是什么?_哔哩哔哩_bilibili

相关推荐
葫芦和十三5 小时前
图解 MongoDB 26|片键设计:决定集群命运的一个决定
后端·mongodb·agent
Avan_菜菜6 小时前
使用 Docker + rclone 自建 WebDAV
后端·agent·claude
小bo波7 小时前
Java Swing 图形用户界面实验 —— 从算术练习到游戏开发的完整实践
java·课程设计·gui·游戏开发·扫雷·swing
阳光是sunny7 小时前
别再被 worktree 绕晕了!AI 编程时代你必须掌握的 Git 隔离神器
前端·人工智能·后端
万少9 小时前
万少的博客 - 技术分享与解决方案
前端·javascript·后端
咖啡八杯9 小时前
GoF设计模式——备忘录模式
java·后端·spring·设计模式
苍何9 小时前
腾讯再放大招,企微 Agent 大圆开启内测
后端
ethantan9 小时前
一篇讲解AI Agent 组成:像人一样思考的智能体
人工智能·后端·程序员
Cosolar11 小时前
vLLM 生产级部署完全指南
人工智能·后端·架构
IT_陈寒12 小时前
垃圾回收器选错了,我的Java服务内存炸了
前端·人工智能·后端