本篇文章主要介绍Bean的加载流程,以及Spring是怎么解决循环依赖的问题。 老规矩,图先上,结合图和源码一起才能更好的理解,首先看下Bean的加载的是时序图:
接下来是看下SpringBoot启动过程初始化所有非懒加载Bean的入口代码,结合上面的时序图,进入主要代码的解读。
梳理下大致的流程:
- 从单例加载bean,spring里bean为什么是单例的是个老生常谈的问题了
- 实例化bean
- 依赖检查,在这一步一般会报依赖找不到或者依赖项目因为版本原因接口报错
- 转化BeanDefinition为RootBeanDefinition
- 对不同的作用域进行bean的创建
- 类型转换
接下来继续结合上面的时序图分析
@1.1 getSingleton(beanName) 从缓存中获取单例bean
上述代码可知Spring会先从singletonObjects中获取Bean,获取不到再从earlySingletonObjects中获取,在获取不到就从singletonFactories获取对应的Objecfactory,调用getObject()方法去创建bean.解释下上边几个map的作用。 也就是说Spring的bean在处于不同阶段的时候会由不同的缓存去存贮。
@1.2 getMergedLocalBeanDefinition(beanName)
这个方法会将BeanDefinition转为RootBeanDefinition,如果是子类的话还可以合并父类的BeanDefinition,大致说下RootBeanDefinition是干嘛的,其实就是用来定义Bean的,该Bean是什么类型的,需要注入的属性,定义Bean的构造方法等,因篇幅问题只叙述Bean的加载过程,不多在概述。
@1.3 getSingleton(beanName, ObjectFactory) ,这个方法的参数是一个beanName,和一个内部类,内部类的方法返回的是createBean(beanName, mbd, args)字面意思就是创建Bean,下面开始深入此方法(省略部分)。
梳理下,流程如下:
- 判断该Bean是否加载过
- 没有加载,记录beanName的状态
- 调用createBean创建Bean(重点)
- 调用Bean创建完成后的方法
- 加入缓存,并移除各种辅助状态
下一节继续解读创建bean和bean的实例化以及加载方法还有就是循环依赖的处理。