面试组合技-月色血风暴,什么是Spring中的循环依赖?怎么解决循环依赖?

126 阅读2分钟

💄💄💄今年的铜三铁四到了,给大家写几篇面试题解析

👠什么是Spring中的循环依赖?

A依赖于B

在这里插入图片描述

B依赖于A

在这里插入图片描述

对应的xml文件

在这里插入图片描述

关系图

在这里插入图片描述

👢Spring怎么解决循环依赖?

spring使用了三级缓存来解决依赖,把bean的实例化和初始化分开存放

在这里插入图片描述

一级缓存singletonObjects:存放初始化完成后的bean 二级缓存earlySingletonObjects:存放实例化完成后的bean 三级缓存singletonFactories:解决有aop代理的bean的循环依赖问题

👕流程图

在这里插入图片描述 在线流程图

准备debug环境:

在这里插入图片描述

进入ClassPathXmlApplicationContext的构造方法

在这里插入图片描述

finishBeanFactoryInitialization方法

在这里插入图片描述

preInstantiateSingletons方法

在这里插入图片描述

getBean方法

在这里插入图片描述

doGetBean方法

在这里插入图片描述

getSingleton方法

在这里插入图片描述

去一级缓存里面拿a

在这里插入图片描述

返回的singletonObject为空

在这里插入图片描述

👔缓存内部情况1

在这里插入图片描述

返回的a为空,一级缓存里面没有a对象

在这里插入图片描述

getSingleton方法

在这里插入图片描述

调用lambda方法

在这里插入图片描述

createBean方法

在这里插入图片描述

doCreateBean方法,实例化a对象

在这里插入图片描述

getWrappedInstance方法,完成a的创建,底层使用反射创建对象

在这里插入图片描述

addSingletonFactory方法

在这里插入图片描述

向三级缓存加a对象

在这里插入图片描述

👒缓存内部情况2

此时缓存情况,a对象b属性为null

在这里插入图片描述

populateBean方法

在这里插入图片描述

applyPropertyValues方法,填充b属性

在这里插入图片描述

resolveValueIfNecessary方法

在这里插入图片描述

resolveReference方法,处理b属性

在这里插入图片描述

getBean方法,又回到了这个方法

在这里插入图片描述

getSingleton方法

在这里插入图片描述

此时没有缓存中没有b对象

在这里插入图片描述

createBean方法,创建b对象

在这里插入图片描述

👗缓存内部情况3

到目前为止,a和b对象的情况为

在这里插入图片描述

addSingletonFactory方法

在这里插入图片描述 在这里插入图片描述

🎽缓存内部情况4

此时缓存里面的情况为

在这里插入图片描述

populateBean方法,给b对象里面的a属性填充值

在这里插入图片描述

applyPropertyValues方法

在这里插入图片描述

又回到了上面的方法applyPropertyValues,第二次出现,又回到了getSingleton方法,从一级缓存里面找a对象

在这里插入图片描述

一级找不到

在这里插入图片描述

二级找不到

在这里插入图片描述

三级找到了

在这里插入图片描述

拿到了半成品的a

在这里插入图片描述

往二级缓存添加a对象,三级缓存删除a对象

在这里插入图片描述

👖缓存内部情况5

此时的缓存情况,三级缓存移除a,二级缓存添加a

在这里插入图片描述

从三级级缓存拿取到a半成品

在这里插入图片描述

将a的值赋值给b

在这里插入图片描述 在这里插入图片描述

👘缓存内部情况6

此时a和b的情况

在这里插入图片描述 在这里插入图片描述

addSingleton方法

在这里插入图片描述

此时的b已经是成品了,所以一级缓存添加b,二三级缓存删除b

在这里插入图片描述

🎀缓存内部情况7

现在的缓存情况

在这里插入图片描述

一级缓存已经有了b对象成品,所以只要给对象a赋值就行了

在这里插入图片描述

addSingleton方法

在这里插入图片描述

一级缓存添加a,二三级缓存删除a

在这里插入图片描述

🎩缓存内部情况8

所以此时的缓存情况 在这里插入图片描述

我们后面从ioc容器中拿取a对象都是从一级缓存里面直接拿a的成品

在这里插入图片描述 在这里插入图片描述