【Spring】Spring5 源码中常用接口的底层原理
本文将介绍Spring源码中较为常用的几个接口的底层实现原理:
- ImportBeanDefinitionRegistrar
- BeanPostProcessor
- BeanFactoryPostProcessor
- BeanDefinitionRegistryPostProcessor
- Aware
ImportBeanDefinitionRegistrar
ImportBeanDefinitionRegistrar
接口的实现类用在@Import
注解中,用于向IoC容器中自定义注册组件。
1 |
|
@Import
注解中可以传入ImportBeanDefinitionRegistrar
接口的实现类。
xxx通过调用ImportBeanDefinitionRegistrar
接口实现类的registerBeanDefinitions()
方法,可以自定义地给容器中添加组件。方法参数:
importingClassMetadata
:当前标注Import注解的类(即SpringConfig类)的所有注解信息registry
:所有bean对象都通过此对象注册,可以使用该对象给容器中注册一个bean
使用方法:把所有要添加到容器中的bean调用registry.registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
方法手动注册到容器中。该方法需要传入beanName
和一个实现了beanDefinition接口的类的对象(通常使用其实现类RootBeanDefinition)
使用实例:
BeanPostProcessor
BeanPostProcessor:bean后置处理器。其用于在bean的初始化前后进行一些处理工作(此时已经调用了构造函数并使用了set方法为bean赋值):
postProcessBeforeInitialization()
:在初始化方法之前工作postProcessAfterInitialization()
:在初始化方法之后工作
自定义后置处理器实现BeanPostProcessor
的方法,并将其注册到容器中。之后所有的bean对象在初始化方法前后都会进入该类的方法中执行相应处理。
1 |
|
BeanPostProcessor执行流程源码分析
- 容器调用bean的构造方法创建对象
populateBean()
:容器调用bean的set方法为bean对象的属性赋值(红色框)initializeBean()
:容器为bean做初始化操作(黄色框)
方法栈位置:AbstractAutowireCapableBeanFactory.java
======> 进入黄色框的initializeBean()
方法:
- 执行
invokeAwareMethods()
方法(绿色框) - 执行
applyBeanPostProcessorsBeforeInitialization()
方法(红色框) - 执行
invokeInitMethods()
方法完成初始化(黄色框) - 执行
applyBeanPostProcessorsAfterInitialization()
方法(红色框)
======> 进入红色框的applyBeanPostProcessorsBeforeInitialization()
方法:
遍历得到容器中所有的BeanPostProcessor
,并一执行BeanPostProcessor
的postProcessBeforeInitialization()
方法,将bean对象逐一经过每个BeanPostProcessor
处理器。一旦返回null,跳出for循环后续不再执行。
BeanFactoryPostProcessor
BeanFactoryPostProcessor:bean工厂后置处理器。调用时机:在BeanFactory标准初始化之后调用,此时所有组件的定义已经加载,但是组件的实例还没有被初始化创建。其作用:用来定制和修改BeanFactory的内容。
1 |
|
BeanFactoryPostProcessor执行流程源码分析
- 在
refresh()
方法中调用invokeBeanFactoryPostProcessors()
:
- 在其内的方法栈中先按照类型获取到
postProcessorNames
- 将获取到的:
postProcessorNames
按照优先级排序
- 按照优先级次序依次执行
上述过程在初始化创建其他组件之前执行,在BeanDefinitionRegistryPostProcessor之后执行。
BeanDefinitionRegistryPostProcessor
BeanDefinitionRegistryPostProcessor继承自BeanFactoryPostProcessor。其在所有bean定义信息将要被加载,且bean实例还未创建时执行,因此其在BeanFactoryPostProcessor
的方法之前执行。作用:利用传入的BeanDefinitionRegistry给容器中再添加一些组件。
每个BeanDefinitionRegistryPostProcessor
接口的实现类都需要实现postProcessBeanDefinitionRegistry()
方法和postProcessBeanFactory()
方法,执行顺序:先前者再后者。
1 |
|
BeanDefinitionRegistryPostProcessor执行流程源码分析
- 在
refresh()
方法中调用invokeBeanFactoryPostProcessors()
:
- 在其内的方法栈中先按照类型获取到
postProcessorNames
- 之后同样按照优先级依次执行
invokeBeanDefinitionRegistryPostProcessors()
(红色框)
invokeBeanDefinitionRegistryPostProcessors()
:
- 执行完
invokeBeanDefinitionRegistryPostProcessors()
后再执行invokeBeanFactoryPostProcessors()
(黄色框)
invokeBeanFactoryPostProcessors()
:
注意:上述过程均在BeanFactoryPostProcessor组件的方法执行前执行。
其与BeanFactoryPostProcessor执行时机对比
首先从容器中获取到所有的BeanDefinitionRegistryPostProcessor
组件,依次触发其postProcessBeanDefinitionRegistry()
方法,再触发postProcessBeanFactory()
。
之后再从容器中找到 BeanFactoryPostProcessor
,并执行其postProcessBeanFactory()
。
即执行顺序:
BeanDefinitionRegistryPostProcessor.postProcessBeanDefinitionRegistry()
BeanDefinitionRegistryPostProcessor.postProcessBeanFactory()
BeanFactoryPostProcessor.postProcessBeanFactory()
Aware
1 | /** |
Aware接口有若干继承的接口,命名格式为xxxAware:
开发人员自定义的组件若想使用Spring底层的一些组件(如ApplicationContext、BeanFactory等),只需要实现相应的xxxAware(如ApplicationContextAware、BeanFactoryAware)接口,这些接口均继承自Aware接口,其特有的方法会以callback-style的方式被容器中对应的xxxAwareProcessor组件调用。
每个Aware接口实现类都对应了一个xxxAwareProcessor类(如ApplicationContextAware对应ApplicationContextAwareProcessor),该Processor类负责在容器中创建组件后(初始化之前)以回调的风格调用xxxAware实现类的特定方法(每个xxxAware实现类都有其特有的方法,功能都不同)。容器在逐一注册bean时,若发现某个bean实现了某个Aware接口,就会在容器中注册相应的xxxAwareProcessor类组件,让其负责回调该bean中实现的xxxAware接口的方法。
例如:ApplicationContextAware接口对应了一个ApplicationContextAwareProcessor类:
若开发人员自定义的某个bean(如下图中BookDao类)实现了ApplicationContextAware
接口的setApplicationContext(ApplicationContext applicationContext)
方法,则在容器加载BookDao
类时,会根据其实现的ApplicationContextAware
接口动态注册一个ApplicationContextAwareProcessor
类。
IoC容器在执行到方法栈AbstractAutowireCapableBeanFactory.java
时,会遍历得到容器中所有的BeanPostProcessor
,并一执行BeanPostProcessor
的postProcessBeforeInitialization()
方法,将bean对象逐一经过每个BeanPostProcessor
处理器,此时会调用:
ApplicationContextAwareProcessor
类实现的postProcessBeforeInitialization()
方法如下:
每个bean在进入该方法后都会判断是否符合黄色框中接口的实现类,若符合(代表实现了xxxAware接口),则会执行invokeAwareInterfaces()
方法,根据其实现的接口类型调用相应的方法设置相应的容器组件(红色框)。
注意:在创建bean之前调用的invokeAwareMethods()方法(绿色框)内只会调用三个特殊的Aware接口实现类的方法,其他的Aware接口并不会在此执行,只能通过创建相应xxxAwareProcessor的方式回调执行相应方法。