💄💄💄今年的铜三铁四到了,给大家写几篇面试题解析
文章目录
👠什么是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的成品