IOC流程解析-BeanFactoyPostProcessor和BeanPostProcessor
本次内容要讲的是BeanFactory 创建完成并设置了BeanDefinition 之后,BeanFactoyPostProcessor 的初始化和执行,还有BeanPostProcessor 的初始化,注意今天的内容BeanPostProcessor 是不会执行的,在 Spring的基本概念和IOC流程的简述 的文章就说过了IOC 的流程图,BeanPostProcessor 的执行是在Bean 实例化之后。
源码分析
接着上篇文章(上篇文章是: IOC流程解析-BeanFactory的创建)继续讲IOC 的核心方法refresh 方法的内容,之前讲完了obtainFreshBeanFactory 方法的调用,那么下一步就是prepareBeanFactory 方法了。
Bean工厂的前置操作-prepareBeanFactory方法
这个方法不是重点方法,所以代码就不细说了,按照代码流程简单说一下这个方法的主要了些什么,作用如下:
- 首先就是给beanFactory 设置一些属性,如类加载器、注册解析器之类;
- 然后就是添加第一个beanPostProcessor 后置处理器(注意:这里是bean,不是beanFactory),这个后置处理器会添加到beanFactory 的私有常量集合beanPostProcessors 集合属性中,而这个后置处理器ApplicationContextAwareProcessor 处理器,其主要作用就是为了在bean 初始化的时候,判断bean 是否都实现了ApplicationContextAware、EnvironmentAware之类接口,然后为其注入对应的applicationContext 对象;
- 然后就是设置一些忽略接口,比如刚刚说的ApplicationContextAware,因为这些spring 自己会做处理,接着就是对特殊的几个bean依赖做处理,这里不用深究;
- 然后就是添加第二个beanPostProcessor 后置处理器,这个是ApplicationListenerDetector 处理器,其主要做用就是为实现ApplicationListener 接口的对象初始化的时候,将其注册到一个监听列表中。这里涉及到spring 的事件传播机制,这个后续再说,会结合上篇所说到的dubbo 标签解析内容一起再细说一次;
- 最后一个重点,这里会创建三个完整对象,并添加到单例池中,单例池就是beanFactory 的私有常量集合singletonObjects 集合,这也是我们常说的IOC 容器、一级缓存。后面bean 初始化完成后得到的完整对象就是存入这个集合中。说回三个完整对象,其实就是对系统和beanFactory 的一些配置信息,后面需要使用的话可以直接通过对象获取。
Bean工厂后置操作-postProcessBeanFactory方法
prepareBeanFactory方法结束后,接下来就是postProcessBeanFactory 方法,但是这个方法就是提供一个模板,可以自己实现接口,重写这个方法来实现自己的业务逻辑,它本身没有任何的代码逻辑。
调用bean工厂后置处理器-invokeBeanFactoryPostProcessors 方法
这一步就已经到了BeanFactoryPostProcessors 的构建和调用过程了,也算是今天的重点之一。
跟进具体方法,其重点是继续invokeBeanFactoryPostProcessors 方法的调用,继续跟进的话,这里的内容就多了去了,不过逻辑并不复杂,我们一步一步跟重点看。不过这里需要注意一点该方法的第二个入参getBeanFactoryPostProcessors 方法返回值,这里是当前应用上下文中已经注册的BeanFactoryPostProcessor,也就是只有多容器启动的时候这个返回才有值。
1 | // 1.getBeanFactoryPostProcessors(): 获取当前应用上下文中已经注册的 BeanFactoryPostProcessor |
进入invokeBeanFactoryPostProcessors 方法。
第一步:判断beanFactory
判断beanFactory 是否为BeanDefinitionRegistry,之前Spring的基本概念和IOC流程的简述 文章中介绍bean 组件的时候有说过beanFactory 的最底层子类是DefaultListableBeanFactory,而该类又实现了BeanDefinitionRegistry,我们目前传入的对象就是DefaultListableBeanFactory,所以这里一定是满足的。
然后看到这里会声明两个集合,一是:用于保存普通的BeanFactoryPostProcessor类型的后置处理器、还有一个是:保存BeanDefinitionRegistryPostProcessor类型的后置处理器,由此可以知道BeanFactory 后置处理器为两个实现类型。
1 | // 1. 判断beanFactory是否为BeanDefinitionRegistry |
BeanFactory后置处理器-BeanDefinitionRegistryPostProcessor
BeanFactoryPostProcessor 这个后置处理器没有什么好说的,只要实现了这个接口,那么就是BeanFactory 的后置处理器。
我们目前要知道的是BeanDefinitionRegistryPostProcessor,这个接口是BeanFactoryPostProcessor 接口的子类接口。它这里可以看做是对于原本普通的BeanFactoryPostProcessor 进行了一次加强,也就说如果实现该接口,不光要实现BeanFactoryPostProcessor 接口的方法,还要实现该接口本身的方法。
1 | public interface BeanDefinitionRegistryPostProcessor extends BeanFactoryPostProcessor { |
第二步:处理入参的BeanFactoryPostProcessor集合
这里继续刚刚的invokeBeanFactoryPostProcessors 方法。
接下来是处理刚刚传入参数的BeanFactoryPostProcessor 集合,也就是上面说的getBeanFactoryPostProcessors 方法的返回值。这里的处理也就是简单的调用而已,因为这个集合是注册在其余容器中了的,所以优先级之类的已经处理过了,这里我们不重点看。
但是需要注意的是:这里执行的只有BeanDefinitionRegistryPostProcessor 的实现,BeanFactoryPostProcessor 的实现类是没有执行对应的方法的,但是这个两种接口实现都会存入上面声明的集合。
第三步:处理当前BeanDefinitionRegistryPostProcessor的PriorityOrdered实现
下一步是再次声明一个集合用于保存本次要执行的BeanDefinitionRegistryPostProcessor。
然后就是通过beanFactory 获取到所有的实现了BeanDefinitionRegistryPostProcessor 接口的对象,这里我们其实还可以看出:如果存在多个执行器的话,目前的执行顺序就是配置信息的解析顺序。
接下来就是循环上面获取的集合,然后就是筛选出接口实现,并添加相应集合。
然后在此将要执行的集合再次排序,依据就是否是实现了Ordered 接口,还有其接口实现的order 值。然后添加上面声明的registryProcessors 集合,最后执行处理好的currentRegistryProcessors 集合,并在执行完成之后清空关闭该集合。
1 | // 定义集合:用于保存本次要执行的BeanDefinitionRegistryPostProcessor |
第四步:处理当前BeanDefinitionRegistryPostProcessor的Ordered实现
逻辑跟上面一样,先获取、再筛选、再排序、最后执行实现对象的对应方法,并清空关闭集合。没有什么可以聊的,不过需要注意的是这里和上面执行的都是BeanDefinitionRegistryPostProcessor 接口的postProcessBeanDefinitionRegistry 方法,BeanFactoryPostProcessor 接口对应的方法是还没有执行的。
对了这里还要注意一个校验执行过的,是不能重复执行的,也就是processedBeans 集合的作用。
1 | // 4.调用所有实现了Ordered接口的BeanDefinitionRegistryPostProcessor实现类(过程跟上面的步骤3基本一样) |
执行优先级-PriorityOrdered接口和Ordered接口
这两个接口的优先级,从上面的代码也可以看出来PriorityOrdered 接口实现要优先于Ordered 接口实现。PriorityOrdered 接口更像是一个标识,它本身没有方法,它的父类就是Ordered 接口,这个接口有一个getOrder 方法,用于编写优先级。具体实现如下。其返回数字越大,优先级越大。
1 |
|
第五步:执行剩下的BeanDefinitionRegistryPostProcessors
首先是通过循环筛选出剩下的所有BeanDefinitionRegistryPostProcessors 的实现类,然后排序、添加集合、执行调用该接口的postProcessBeanDefinitionRegistry 方法,清空关闭currentRegistryProcessors 集合,老套路了,没有什么好说的。
1 | // 5.最后, 调用所有剩下的BeanDefinitionRegistryPostProcessors |
第六步:执行所有的BeanDefinitionRegistryPostProcessors实现的postProcessBeanFactory方法
到这里是执行所有的,注意是所有的BeanDefinitionRegistryPostProcessors 实现的postProcessBeanFactory方法,也就是其父类接口对应的方法,之前执行的方法都是它自己定义的,然后是执行入参集合中的postProcessBeanFactory方法。
这里所有的BeanDefinitionRegistryPostProcessors 实现算是执行完成了。
1 | // Now, invoke the postProcessBeanFactory callback of all processors handled so far. |
第七步到最后一步:执行BeanFactoryPostProcessor的实现
这里就不展示代码了,因为套路是一模一样的,唯一的区别就是获取的接口实现不一样而已。
这个方法就算是结束了。
小结:方法作用及优先级顺序
这个方法其主要作用就是执行所有的BeanFactoryPostProcessor 接口和子类接口的相关实现,如果是多容器启动的话,其余容器的BeanFactory 执行器也要再次执行。
不同方法执行优先级总结:其余容器的BeanDefinitionRegistryPostProcessors 实现的postProcessBeanDefinitionRegistry 方法 > 当前容器的BeanDefinitionRegistryPostProcessors 实现的postProcessBeanDefinitionRegistry 方法 > 其余容器的BeanDefinitionRegistryPostProcessors 实现的postProcessBeanFactory 方法 > 当前容器的BeanDefinitionRegistryPostProcessors 实现的postProcessBeanFactory 方法 > 其余容器的BeanDefinitionPostProcessors 实现的postProcessBeanFactory 方法 > 当前容器的BeanDefinitionPostProcessors 实现的postProcessBeanFactory。
同一方法执行优先级总结:实现PriorityOrdered 接口 > 实现Ordered接口 > 配置文件配置顺序;实现同一接口是:按照getOrder 方法返回的数字排序,数字越大优先级越高。
注册Bean后置处理器-registerBeanPostProcessors方法
看完了bean工厂后置处理器的执行,在回到核心refresh 方法继续看。
接下来是Bean 的后置处理器,注意不是beanFactory 的了,同时这里是register 注册没有调用的内容。清楚这点后,我们再看代码。
跟进方法,没有什么内容就是调用PostProcessorRegistrationDelegate 对象的注册方法,继续跟进后内容跟上面的一样多,不过都是老套路,我们就看下区别点就行了。
1 | protected void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory) { |
跟进该方法。
首先获取所有的BeanPostProcessor 接口的实现。
1 | // 1.找出所有实现BeanPostProcessor接口的类 |
然后记一下数据量,并存入beanFactory 中。
1 | // BeanPostProcessor的目标计数 |
然后就是老三样、筛选、排序、保存集合、然后注意这里不是执行对应接口方法,而是注册。
1 | // 5.2 注册priorityOrderedPostProcessors |
也就是存入beanFactory 中。不过这里其实已经添加过几个BeanPostProcessor 了,就是上面的前置作用内容添加的。
1 | private static void registerBeanPostProcessors( |
说到上面添加的处理器,这个方法的最后一部分就是想将它们再次注册,也就是移动到处理链末尾。
然后这个方法就结束了。
1 | // 8.最后, 重新注册所有内部BeanPostProcessors(相当于内部的BeanPostProcessor会被移到处理器链的末尾) |
Bean后置执行器的实现-BeanPostProcessor接口
这里还要说一点就是Bean 后置执行器就是BeanPostProcessor 接口的实现,这一点从上面的代码中也可以看出来,我们这里要说的是BeanPostProcessor 接口中的postProcessBeforeInitialization 方法和postProcessAfterInitialization 方法,这两个方法名称的差别非常的小,要注意看前者是Before,后者是After。从名字看也能知道前者是前置方法,后者是后置方法,这样读起来也很有意思,Bean后置执行器的前置方法和后置方法。
1 | public interface BeanPostProcessor { |
结合之前文章[Spring的基本概念和IOC流程的简述](https://liwqtm.github.io/2022/04/09/Spring IOC(一)/#more) 的IOC 流程图可以看出,这两个方法的执行时机是在bean 的初始化部分,同时After 后置方法还存在aop 的实现内容,这个我们后面再说,目前要明白Bean 后置执行器是如何去实现的,并且重写了哪两个方法即可。
总结
本次就是继上篇IOC流程解析-BeanFactory的创建 后说了refresh 核心方法中的后面四个方法,其主要作用就是BeanFactory 的前置操作、BeanFactory 的后置处理器执行、Bean 后置处理的注册。简单来说还是一些BeanFactory 的处理,是实例化和初始化之前的大部分内容了,后面就是初始化和实例化了。
附录Spring 源码分析系列文章
IOC
时间 | 文章 |
---|---|
2022-03-09 | Spring的基本概念和IOC流程的简述 |
2022-03-11 | IOC流程解析-BeanFactory的创建 |
2022-03-14 | IOC流程解析-BeanFactoyPostProcessor和BeanPostProcessor |
2022-03-15 | IOC流程解析-实例化和初始化 |
2022-03-17 | IOC流程解析-循环依赖 |
AOP
时间 | 文章 |
---|---|
2022-03-19 | AOP流程源码分析-配置信息解析和代理对象创建 |
2022-03-20 | AOP流程源码分析-请求调用全流程 |