| |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
-> Java知识库 -> Spring原理篇(8)--循环依赖到底是如何解决的?你只需要看这一篇原理;你就知道循环依赖是怎么解决的; 就很神奇 对不对? -> 正文阅读 |
|
[Java知识库]Spring原理篇(8)--循环依赖到底是如何解决的?你只需要看这一篇原理;你就知道循环依赖是怎么解决的; 就很神奇 对不对? |
@TOC# Spring系列 现在这个章节 我们来到了Spring的循环依赖; 我们在现实项目中处处可见; 因为Spring的机制 帮我们解决了循环依赖; 所以我们就可以不用再关注循环依赖了玛? 如果面试过程中 别人问你 循环依赖是怎么解决的 你怎么回答?. Spring 循环依赖;第一个问题 : 什么是循环依赖?什么是循环依赖? 很简单的一个问题; 给一个案例
这就是循环依赖; 当 Spring 容器中 (ioc) ABean 里面有一个 属性 B , BBean 有一个属性 A;他们相互引用; 注意 是在IOC容器中; 如果不是在容器中 这样写 是没有问题的; 我们把实体交给Spring管理 实际上是管理的实体的生命周期; 也就是Bean的生命周期;
A创建
需要B
B创建
需要A
通过上面这个图 我们很简洁明了的知道; 他们在做一个循环; 他们的问题是出在了Spring的生命周期里面 我们在上面一个篇章讲到; Spring启动的依赖注入; 但是却没有陈述这部分 循环依赖;
第二个问题 : Spring是如何却循环依赖的?在Spring中,通过某些机制帮开发者解决了部分循环依赖的问 题,这个机制就是三级缓存。 一级缓存 singletonObjects单例池; 也就是singletonObject 我们创建对象的时候 首先就会去单例池寻找一下 看以下是否有这个单例池; 以下是源码展示: 在doGetBean的方法内:
这里不过多的去陈述 二级缓存 earlySingletonObjectsearlySingletonObjects 比singletonObjects多了一个early,表示缓存的是早期的bean对象。 早期是什么意思?表示Bean的生命周期还没走完就把这个Bean放入了earlySingletonObjects。 三级缓存 ingletonFactoriessingletonFactories中缓存的是ObjectFactory,表示对象工厂,表示用来创建早期bean对象的 工厂。 如果说现在 要我们去解决循环依赖; 我们要有什么思路去解决? 从上面这个解决方案中, 是不是比较完美的一个解决方案.? 实际上在上面的方案中 缺少了Spring的另外一个重要的功能体系; aop这里不会累赘AOP的原理以及源码; 仅仅是抛出一个问题:
我们根据上面的解决方案 我们在B的注入点里面 保存了A的原始对象. 那么 A要是个含有切面的代理对象 承接上面一个篇章 的 doCreateBean 源码中我们写到 有一句话: 是解决循环依赖; 循环依赖将放在下个篇章去讲; 如果上一个篇章没有看的同学 可以去看一下; 以下是源码:
getEarlyBeanReference
InstantiationAwareBeanPostProcessorAdapter
AbstractAutoProxyCreator
1:A创建时
2:A原始对象生成一个ObjectFactory
3:需要B
4:B去创建
5:需要A
6:B创建完成
7:将B赋值给A对象
8:AB对应的Bean都创建完
singletonObjects
总结配上图 在节点 (2)中: ObjectFactory就是上文说的labmda表达式,中间有getEarlyBeanReference方 法,注意存入singletonFactories时并不会执行lambda表达式,也就是不会执行 getEarlyBeanReference方法; 2:我们这个时候得来理解一下earlySingletonObjects的作用,此时,我们只得到了A原始对象的代理对 象,这个对象还不完整,因为A原始对象还没有进行属性填充,所以此时不能直接把A的代理对象放 入singletonObjects中,所以只能把代理对象放入earlySingletonObjects,假设现在有其他对象依 赖了A,那么则可以从earlySingletonObjects中得到A原始对象的代理对象了,并且是A的同一个代 理对象。 3:当B创建完了之后,A继续进行生命周期,而A在完成属性注入后,会按照它本身的逻辑去进行AOP, 而此时我们知道A原始对象已经经历过了AOP,所以对于A本身而言,不会再去进行AOP了,那么怎 么判断一个对象是否经历过了AOP呢?会利用上文提到的earlyProxyReferences,在 AbstractAutoProxyCreator的postProcessAfterInitialization方法中,会去判断当前beanName是 否在earlyProxyReferences,如果在则表示已经提前进行过AOP了,无需再次进行AOP。 4:对于A而言,进行了AOP的判断后,以及BeanPostProcessor的执行之后,就需要把A对应的对象放 入singletonObjects中了,但是我们知道,应该是要把A的代理对象放入singletonObjects中,所以 此时需要从earlySingletonObjects中得到代理对象,然后入singletonObjects中。 整个循环依赖解决完毕;最后祝各位中秋节快乐 我们之后再见; see you |
|
|
上一篇文章 下一篇文章 查看所有文章 |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 | -2024/11/23 17:11:11- |
|
网站联系: qq:121756557 email:121756557@qq.com IT数码 |