Spring之Bean生命周期源码分析(二)
一、前言
Spring专栏全部内容如下:
前世今生
二、getBean方法的使用
三、getBean()方法的流程
如图所示, getBean方法内部是方法重载到了 doGetBean方法
如下图所示, 我们看 doGetBean方法, 可以看到他的一个大概流程
- 先是通过 transformeBeanName(name)方法去获取到 beanName
- 通过 beanName去单例池中拿取对象
- 判断对象是否存在, 然后通过不同的方式去获取 bean对象
下图是 doGetBean()方法的末尾, 可以看到不管前面我们是否获取到了 单例实例对象 我们获取到的 beanInstance最后都执行了同一个方法
若获取到了 bean单例实例对象
那就直接执行以下方法, 去获取 bean对象
若没有获取到 bean单例实例对象
第一个if判断
这个if判断是去看当前 beanName是不是一个原型Bean并记录, 具体后面讲
第二个if判断
流程简单说明:
- 通过当前 beanName去获取到 父BeanFactory
- 如果 父BeanFactory不为null 且通过 beanName获取不到 BeanFactory
- 则去拿取 父BeanFactory并返回
第三个if判断
第四个if判断
这个是java的JFR相关的知识, 有机会我会出一篇文章专门讲一下, 现在忽略掉
第五个if判断
简单流程说明:
- 通过 beanName去创建 BeanDefinition
- 检查 BeanDefinition是不是抽象的
- 之前有讲过, 感兴趣的可以去看我上篇文章
- 判断当前取出的 BeanDefinition有没有实现 @DependsOn注解
- 关于 @DependsOn注解下面有讲
- 若实现了, 则遍历
- 若未实现则跳过下面的方法, 继续向下执行
- 判断有没有出现循环依赖
- 若出现循环依赖则爆异常
- 将 dep与 beanName存入map
- 递归执行 getBean生成被依赖的 dep的 bean对象
假如一个Bean实现了 @DependsOn注解, 如下图所示, 则在创建 JuejinService这个 bean对象之前, 必须先去创建 NingxuanService的 Bean对象
具体代码如下图所示
第六个if判断
这边再往下走, 我们可以看到, 他去判断当前 合并BeanDefinition是单例Bean, 原型Bean, 还是其他类型Bean
单例Bean
流程简单说明:
- 创建 Bean
- 将单例Bean放入单例池中
具体的 createBean()方法后面单独小标题讲解
如图所示, 在这个方法中, 主要执行了 getSingleton方法, 这个方法的入参还有一个 lambda表达式, 那么我们进入这个方法看一下
getSingleton方法简单流程如下:
- 加锁
- 上单例池中找一下
- 如果不存在
- 执行入参的lambda生成单例Bean
- ...
- 将当前单例Bean加入单例池中
中间还有一些依赖相关的步骤, 后续会单独出一个章节讲解依赖注入
原型Bean
简单流程说明:
- 记录当前Bean正在创建
- 创建原型Bean
- 在正在创建的Bean中删除当前Bean
- 调用 ObjectForBeanInstance获取真正的Bean对象
其他类型Bean
简单流程说明:
- 获取当前 bean上@Scope注解的value值
- 通过拿到的 value值去获取 Scope的实际对象, 通过多态
- 若没有拿到具体的实际对象则抛出异常, 说明你传进来的 value有问题
- 若拿到了则执行和单例差不多的方法
- 判断当前 beanName的实例Bean是否存在
- 存在则返回
- 不存在则通过 lambda创建
- 这里就不进代码里面看了, 很简单的
createBean方法
我们可以看到在不论bean的类型是单例, 还是其他, 都会执行 createBean方法, 下面我们会进入这个方法对其进行详细的讲解
如图所示, 会进行以下步骤:
- 确保beanClass被加载
- 实例化前
- 执行doCreateBean方法
- 返回创建的 bean实例
resolveBeanClass()方法
简单流程说明:
- 判断当前 Bean的Class有没有被加载
- 若被加载了, 则直接返回
- 若没有被加载,则执行 doResolveBeanClass()方法
doResolveBeanClass(方法)
流程简单说明:
- 获取类加载器
- 注意, 这边我们传进来的 typesToMatch 是null, 所以这个if我们暂时忽略掉
- 获取bean类型名称
- 解析Spring表达式
实例化前(后面有讲)
从这里开始具体的流程分析放到下面的大标题去讲解了, 因为我觉得具体的一个流程应该是在一个大标题下面的
doCreateBean()方法
简单流程说明:
- 实例化Bean
- 解决循环依赖
- 填充属性
- 初始化
- Bean的销毁
具体代码如下图所示, 一张图放不下....
由于 doCreateBean()方法内部是比较重要的, 所以我把这个方法拆解成了多个方法, 放在了下面的大标题写
四、实例化前
实例化前的的方法是 resolveBeforeInstantiation()方法, 具体进入实例化前的方法步骤请看上一个标题
设置初始化前要去使用类实现 BeanPostProcessor类, 并实现其内部的两个方法
该方法内部具体的实现如下所示
实例化前的方法执行完毕之后, 就会进入到 doCreateBean()方法
五、属性填充(@Bean方式)
代码如下
这里传进该方法的第三个参数是 bean的实例, bean实例的创建是在 doCreateBean方法中, 具体如下图所示, 正常来讲, 我们已经进行了实例化, 所以这个值是肯定存在的
接着往下走, 会看到一个 mbd.isSynthetic()判断, 这个也后面讲, 然后就看到了hasInstantiationAwareBeanPostProcessors() 这个方法判断, 有没有执行这个BeanPostProcessors
六、实例化后
这个很少能用到了, 就暂时不做讲解了, 感兴趣的可以自己去看一下
它的配置是在 @Bean注解上写成以下形式, 我们也可以看到, 现在已经不推荐我们使用这个方式去做注解了
@Bean(autowire = Autowire.BY_TYPE)
public void test(){
}
处理属性(@Autowired等注解)
再一次的去判断有没有实现 InstantiationAwareBeanPostProcessor 接口, 如果有的话就遍历去执行 postProcessProperties方法, 这个方法还是很重要的, 在Spring中, 是通过这个扩展点来处理@Autowired, @Resource等注解的
这个方法具体的实现, 我们通过以下方式进入, 通过 InstantiationAwareBeanPostProcessor类找到 postProcessProperties方法, 然后去看具体的实现类 AutowiredAnnotationBeanPostProcessor
实现的 postProcessProperties方法如下图所示, 这个后续也会讲到
初始化
我们回到 doCreateBean方法, 接着往下看初始化方法
该方法详情如下图所示:
Aware
可以看到最开始的核心就是调用了一个方法 invokeAwareMethods(beanName, bean);
下图是这个方法详情, 就不想洗讲了, 大概都能看的懂:
- 判断有没有实现 Aware接口
- BeanNameAware:回传beanName给bean对象。
- BeanClassLoaderAware:回传classLoader给bean对象。
- BeanFactoryAware:回传beanFactory给对象。
初始化前
初始化简单流程说明:
- 循环遍历 BeanPostProcessors
- 执行相应的方法
初始化
初始化简单流程说明:
- 判断有没有实现 InitializingBean
- 实现了调用 ((InitializingBean) bean).afterPropertiesSet();方法
- 如果 BeanDefinition指定了 InitMethodName(初始化方法的名字)
- 就执行对应的方法
初始化后(AOP)
初始化简单流程说明:
- 循环遍历 BeanPostProcessors
- 执行相应的方法
和初始化前的区别就是执行的方法换了
本文内容到此结束了
如有收获欢迎点赞👍收藏💖关注✔️,您的鼓励是我最大的动力。
如有错误❌疑问💬欢迎各位大佬指出。
我是 宁轩 , 我们下次再见
转载自:https://juejin.cn/post/7136492590706688008