SpringIOC+循环依赖
2021-03-11 10:11:25 69 举报
Spring学习笔记
作者其他创作
大纲/内容
属性赋值
this.singletonFactories.get(beanName);
创建B对象
初始化
修改bean信息
填充属性
BeanFactoryPostProcessor
env
json
没有找到
执行init方法
cglib(基于类)
创建A对象
填充B对象中的a属性
A属性填充时发现依赖B,就去getB,重复B的创建流程,发现B依赖A,就去getA,此时在三级缓存中发现A,此时清除三级缓存,将A存入二级缓存,完成B对象的创建,将B对象添加到一级缓存,此时A对象中的B对象完成赋值,A对象创建完成,将A对象添加到一级缓存。
半成品
创建对象
抽象接口定义读取配置文件的规范
实例化A对象
properties
反射
getBean
Environment
BeanPostProcessor.before
Constructor ctor = clazz.getDeclareConstructor();Object obj = ctor.newinstance();
BeanDefinitionReader
doCreateBean
修改beanDefinition信息
缓存中mapK-V
填充A对象中的b属性
总结
直接赋值即可
观察者模式:监听器,监听事件
对属性的属性值都是默认值
在堆中开辟一块内存空间
1、如果只有一级缓存,能否解决循环依赖问题?不能,因为一级缓存中存放成品对象,二级缓存存放的是半成品对象,如果只有一级的话,成品和半成品放在一起,那么就有可能获取到半成品对象,此时会有空指针的问题,所以必须分开存储。2、如果只有二级缓存,能否解决循环依赖问题?直接使用二级缓存可以解决循环依赖问题,但是当添加AOP之后,二级缓存就不不能解决循环依赖问题了,报错显示没有使用最终的bean版本。3、为什么要有三级缓存?三级缓存的目的是处理aop过程中存在动态代理的情况,在getEarlyBeanReference()方法中可能把原来的普通对象替换成代理对象。4、不管是普通对象还是代理对象,对应的bean名称是一致的,那怎么保证普通对象和代理对象只对外暴露一个?通过回调机制来保证,lamda传递到三级缓存之后并不是直接存储的对象,而是在需要对象的时候,调用回调的方法来返回唯一的对象,即对外只暴露一个对象
xml
Ba
jdk(基于接口,默认)
实例化bean
singletonFactory.getObject()
BeanPostProcessor.after
doGetBean
如果我们需要在bean对象的创建过程中,详细了解每一个步骤完成的进度,在不同的阶段做不同的处理工作,就需要监听器和多播器
完整bean对象
动态代理
initializeBean
yaml
从容器中查找A对象
尝试获取三级缓存
AOP
BeanFactory
添加到三级缓存
getSingleton(beanName)
实例化
完成实例化但未完成初始化
对象的两种状态
Ab
如果获取到就调用lamda方法(getEarlyReference)
完成了实例化和初始化
bean定义信息BeanDefication
为了方便使用,在容器创建的时候会提前将系统的相关属性加载到StandardEnvironment对象中,方便后续使用
createBeanInstance
只要持有了该半成品的引用,就可以在后续过程中完成赋值操作
执行初始化方法
找到
实例化B对象
从各级缓存中获取bean
添加到一级缓存,并移除二级和三级缓存
成品
从容器中查找B对象
populateBean
createBean
PostProcessor
设置Aware接口属性
BeanPostProcessor
IOC容器
收藏
0 条评论
回复 删除
下一页