| |
|
开发:
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循环依赖,请一定要把这篇看完(建议收藏) -> 正文阅读 |
|
[Java知识库]【大厂面试】三面三问Spring循环依赖,请一定要把这篇看完(建议收藏) |
?欢迎订阅《大厂面试突击》专栏,面试10多家大厂总结出的重点知识,仅前50名免费?
前言哈喽大家好,我是一条 最近3天面了大约有10家公司,平均一天三面。 有趣的是同一天连着三个面试官问到了 以后再有人问你 概念什么是循环依赖?多个bean之间相互依赖,形成了一个闭环。比如:A依赖于B、B依赖于C、C依赖于A。 通常来说,如果问Spring容器内部如何解决循环依赖,一定是指默认的单例Bean中,基于 循环依赖的种类及能否解决如下:
报错信息
翻译一下
异常信息:bean当前创建异常 通俗版理解两人拿枪对峙现在甲乙两个人,互相拿枪对峙,甲说乙先放,乙说甲先放。就是不开枪。 哎,就是玩! 相信这个场景大家在电视剧里都见过吧,最后一般是“反派死于话多”。 但是回到我们 必须有一人妥协解决方案就是:必须有一个人先妥协。 甲说:我退一步,我先把弹夹卸了,你把枪放下。 乙一听就感动了,满含热泪的拿枪放下了。 甲一看乙没有打自己,也热泪盈眶,两人紧紧相拥。 从此过上了幸福美满的生活…… Spring版理解回到我们
简单理解一下的上面的过程 实例化和初始化什么区别?是不是只差了中间赋值的过程,那只实例化的 当然不可以! 也就是说只实例化的bean是一个半成品,初始化之后才是成品,才可以使用。 现在A依赖B,B依赖A。
ok,两人打起来了,拿枪对峙。怎么解决?是不是得一个人妥协。
如此,A创建了完整的自己,B拿着A也完成了创建。 问题解决。 真的解决了吗?成品和半成品都存在哪里呢? 这就不得不提到大名鼎鼎的三级缓存。 三级缓存
创建过程(简易版)
假如A依赖B,B依赖A,那么这两个类之间形成了一个循环依赖
创建过程(源码版)
1、当我们在调用getBean()获取bean时,实际调用的是doGetBean() 方法。doGetBean() 想要获取 beanA ,于是调用 getSingleton() 方法从缓存中查找 beanA 2、在 getSingleton() 方法中,从「一级缓存」中查找,没有,返回 null 3、doGetBean() 方法中获取到 beanA 为 null ,于是走对应的处理逻辑,调用 getSingleton() 的重载方法(参数为 ObjectFactory 的) 4、在 getSingleton()方法中,先将 beanA_name 添加到一个集合中,用于标记该 bean 正在创建中,然后回调匿名内部类的 createBean 方法 5、进入 AbstractAutowireCapableBeanFactory#doCreateBean,先反射调用构造器创建出 beanA 的实例,然后判断,是否为单例,是否允许提前暴露引用(对于单例一般为true)、是否正在创建中(即是否是在第四步的集合中)判断为 true 则将 beanA 添加到「三级缓存」中 6、对 beanA 进行属性填充,此时检测到 beanA 依赖于 beanB ,于是查找 beanB 7、调用 doGetBean() 方法,和上面 beanA 的过程一样,到缓存中查询 beanB ,没有则创建,然后给 beanB 填充属性 8、此时 beanB 依赖于 beanA ,调用 getSingleton() 获取 beanA ,依次从一级、二级、三级缓存中找、此时从「三级缓存」中获取到 beanA 的创建工厂,通过创建工厂获取到 singletonObject ,此时这个 singletonObject 指向的就是上面在 doCreateBean() 方法中实例化的 beanA 9、这样 beanB 就获取到了 beanA 的依赖,于是 beanB 顺利完成初始化,并将 beanA 从「三级缓存」移动到「二级缓存」中 10、随后 beanA 继续他的属性填充工作,此时也获取到了 beanB ,beanA 也随之完成了创建,回到 getSingleton() 方法中继续向下执行,将 beanA 从「二级缓存」移动到「一级缓存」中 最后
|
|
|
上一篇文章 下一篇文章 查看所有文章 |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
360图书馆 购物 三丰科技 阅读网 日历 万年历 2025年3日历 | -2025/3/4 2:12:20- |
|
网站联系: qq:121756557 email:121756557@qq.com IT数码 |