从spring源码理解IOC的流程以及如何实例化,初始化和解决循环依赖

什么是IOC:

IOC就是(Inversion of Control) 俗称 控制反转
IOC是一种思想,是可以帮我们管理对象,不用我们管理bean之间的耦合关系,也不用管对象是怎么实例化初始化的
这里简单说一下spring加载bean的流程

首先是BeanDefinitionReader接口封装了一些加载读取Bean信息的方法,然后读取到这个信息以后封装成一堆BeanDefinition,然后加载放入BeanDefinitionRegistry的一个map中,BeanDefinitionRegistry向工厂注册这些bean信息,中间会经过一个BeanFatoryPostProcessors接口,可以实现这个接口对bean进行扩展

什么是循环依赖

依赖就是一个bean依赖了另一个bean
如下图:
A类中要注入B这个bean,而B类中要注入A这个bean,互相依赖我们就把它称之为循环依赖

在这里插入图片描述
那么spring是如何解决的循环依赖呢:
首先我们要明白什么是实例化什么是初始化
实例化:创建对象,此时对象还是一个空对象
初始化:为对象赋值填充属性
spring通过实例化和初始化分为两个步骤来解决循环依赖
不明白也没关系,下面就通过源码来具体看看spring是怎么实现的

通过源码看spring究竟是怎么实例化初始化bean并解决bean之间循环依赖关系的:

这里编译的是spring5.0的源码

首先在xml文件中让两个类去相互依赖
在这里插入图片描述
spring容器启动
在这里插入图片描述
调用了构造方法的refresh()方法
在这里插入图片描述
在倒数第二个方法 里面做了准备工作和实例化懒加载的单例bean
在这里插入图片描述
最后一个方法是实例化懒加载的单例bean

首先,spring加载bean大致分为4步,getBean,doGetBean,createBean,doCreateBean。
在这里插入图片描述
这里做完判断以后就会去getBean在这里插入图片描述
进去以后就会看见方法doGetBean

点进去
在这里插入图片描述
会在单例池中get这个bean 也就是一级缓存
在这里插入图片描述
方法实现:
第一次get为空,并且没有被暴露,这里的暴露是指spring在实例话完成后判断如果支持循环依赖那么就会把这个bean放入三级缓存,这个操作称之为暴露bean
返回null在这里插入图片描述
开始创建bean 调用这个方法 key是beanName value是一个lambda表达式 但并没有被执行
在这里插入图片描述
进来发现是先在一级缓存中get这个bean 如果为null 下边掉用了getObject才是调用了createBean
在这里插入图片描述
do开头的方法是做事情的方法 开始创建bean
在这里插入图片描述
这个方法用来实例化bean
在这里插入图片描述
进来以后spring会推断最合适的构造方法 我这个只是测试,调用了最简单的无惨构造
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
到这里以后就完成了bean的实例化
然后跳出来在这里插入图片描述
到这里以后就会把这个bean放入到三级缓存中,这一步操作就是暴露了这个bean
这里传入的也是个lamda表达式 也是没有被执行
在这里插入图片描述
放入三级缓存:
在这里插入图片描述

然后开始初始化这个bean 进行依赖注入在这里插入图片描述
发现有一个属性
然后开始
在这里插入图片描述
在这里插入图片描述
解析一些必要的属性值吧应该 我猜的在这里插入图片描述
这是一个还没准备好的类型,暂时不太明白这个类型的意义
在这里插入图片描述
然后getBean 要给A的B属性装配
又到doGetBean方法 循环一次
在这里插入图片描述
单例池也是获取不到B 会创建一次B
在实例化B后会给B的A属性填充 会开始getBean 而A是已经暴露在了三级缓存中,A还是个半成品,但已经可以让B拿到然后初始化了
这个是getBean的逻辑 首先从一级缓存里拿,然后是二级三级
拿到这个bean B就完成了属性的依赖注入 然后开始初始化这个bean
在这里插入图片描述
在这里插入图片描述
先执行判断这个bean有没有实现aware接口 实现了就调用aware接口的属性填充方法在这里插入图片描述
beanPostProcessors 的postProcessBeforeInitialization方法
在这里插入图片描述
执行initMethod方法 这个方法会判断是否实现了initializationBean接口 如果是就会先调用afterPropertiesSet方法 在调用initMethod
在这里插入图片描述
beanPostProcessors的postProcessAfterInitialization,大名顶顶的AOP就是这个接口实现的
然后B就完成了初始化
在这里插入图片描述
然后把B放到一级缓存中
然后A也能拿到B的bean
在这里插入图片描述
spring官网给出解决循环依赖的思路
在这里插入图片描述

总结一下:spring解决循环依赖主要是将实例化和初始化分开,实例化完成后加入到三级缓存中,使得依赖的bean可以get到他。
bean的实例化初始化过程就是首先先在单例池get这个Bean,调用doGetBean方法,如果没有,会开始创建Bean,doCreateBean,实例化完成后,开始属性的注入,如果依赖其他bean,流程一样,最后属性装配完成后,开始初始化,调用aware接口,beanPostProcessors的before方法,afterPropertySet方法, initMethod方法,beanPostProcessors的after方法,完成初始化
后续会继续加油!!!

Guess you like

Origin blog.csdn.net/m0_48358308/article/details/109518657