spring循环依赖
2023-05-28 17:01:47 0 举报
详解spring循环模式
作者其他创作
大纲/内容
删除:B正在创建标记
createBean
A对象的lambda表达式
实例化B对象a=null
创建B对象
创建对象
放到三级缓存,不处理的缺点
从容器中查找A对象
2.如果一级缓存,能解决循环依赖问题么?答:不能,如果只有一级缓存,那么成品对象和半成品对象会放到一起,这个是没办法区分的,半成品对象不能暴露给外部使用,所以需要两个缓存来分别存放不同状态的对象,一级缓存放成品,二级缓存-存放半成品
将A对象放入三级缓存
将B对象放入三级缓存
没找到
getEarlyBeanReFerenc方法来判断返回代理对象还是原生
doGetBean
半成品对象
循环依赖原理
实例化B(原生)
代理B存入一级缓存
工厂B存入三级缓存
属性注入(代理b)
从三级缓存中获取A对象的lambda表达式
直接赋值即可
放入二级缓存
实例化A(原生)
AOP在此判断,A是否生成代理对象是:返回代理否:返回原生
B(a)
给B对象a属性赋值
初始化后进行aop操作解耦
从容器中查找B对象
工厂A存入三级缓存
debug
完成实例化并且完成初始化
A(b)
初始化B对象给a属性赋值
getObject
从第三级获取到实例后,放到一级缓存,存在问题:按照设计思路,第一级存放的是初始化好的对象,直接放到第一级缓存是不合适的,此时的A对象尚未创建完成
初始化A对象给b属性赋值
A对象完成初始化
单例对象初始化主要分为三步
B对象完成初始化
createBeanInstanc实例化
创建A对象
1.第一步:createBeanInstance:实例化,其实就是调用对象的构造方法实例化对象2.第二步:populateBean初始化-填充属性,这一步主要是对bean对象的属性进行填充,即注入属性,满足依赖3.第三步:initiallizeBean:初始化--增强,这一步该Bean就可以使用了总结:从单例Bean的初始化可以知道,循环依赖主要发生在第二步--填充属性,所以要解决循环引用也应该从这个过程着手
初始化
属性注入(代理a)
找到
AOP流程,生成代理对象B
InitializeBean初始化
从第三级获取到实例化,不处理,下次依然从第三级缓存中获取,如果有其他实例依赖这个对象,会再次对这个对象进行代理,这就导致了重复代理
标记:B正在创建
populateBean填充属性
5.各级缓存的主要作用?一级缓存:singletonObjects成品的对象二级缓存:earlySingletonObjects半成品对象三级缓存:singletonFactories lambda表达式
完成实例化但是未完成初始化
给A对象属性赋值b
4.为什么添加了AOP的操作之后,就需要三级缓存来解决循环依赖问题?(1)在创建代理对象的时候,是否需要生成原始对象?答案肯定是需要的,(2)当创建完成原始对象之后,后续有需要创建代理对象,那么此时就是一个beanName对应有两个对象,(原始对象和代理对象),那么通过beanName引用的时候使用哪个对象? 在整个容器中,有且仅有一个同名的对象,当需要生成代理对象的时候,就要把代理对象覆盖原始对象,(3)程序是怎么知道什么时候要进行代理对象的创建的呢? 那么就需要一个类似于回调的接口判断,当第一次对外暴露使用的时候,来判断当前对象是否 需要去创建代理对象;而三级缓存加了什么操作? 添加了一个getEarlyBeanReference的方法,getEarlyBeanfenerce方法里边的if判断: 如果需要代理返回代理 如果没有代理,返回原生
createBeanInstance
放入的是B对象的lambda表达式
doCreateBean
getBean
直接放到一级缓存的缺点
将三级缓存的A工厂对象删除生成代理A存入二级缓存
populateBean
删除:A正在创建标记
成品对象
1.三个缓存对象,在获取数据的时候,是按什么顺序获取的答:先从一级缓存中获取对象,如果没有再从二级缓存中获取对象,二级缓存中没有再从三级缓存中获取,所以当前级别的缓存中存在对象,那么后面级别的缓存就需要把该对象给移除
实例化A对象
代理A存入一级缓存
实例化A对象b=null
标记:A正在创建
0 条评论
下一页