容器的扩展点(一)BeanFactoryPostProcessor
首先我们先看看官网怎么说的:
从上面这段话,我们可以总结如下几点:
1、BeanFactoryPostProcessor可以对Bean配置元数据进行操作,也就是说,S容器允许BeanFactoryPostProcessor读取指定Bean的配置元数据,并可以在Bean被实例化之前修改它,这里说的配置元数据其实就是我们讲过的Beandefinition.
2、我们可以配置多个BeanFactoryPostProcessor,并且我们只要配置的BeanFactoryPostProcessor实现了order接口的话,我们还可以控制这些BeanFactoryPostProcessor的执行顺序。
接下来我们通过demo来感受下BeanFactoryPostProcessor的作用:
例子:
这里就以官网上的demo为例:
<bean class="org.springframework.context.support.PropertySourcesPlaceholderConfigurer">
<property name="locations" value="classpath:com/something/jdbc.properties"/>
</bean>
<bean id="dataSource" destroy-method="close"
class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName" value="${jdbc.driverClassName}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</bean>
jdbc.driverClassName=org.hsqldb.jdbcDriver
jdbc.url=jdbc:hsqldb:hsql://production:9002
jdbc.username=sa
jdbc.password=root
在上面的例子中,我们配置了PropertySourcesPlaceholderConfigurer,为了方便理解,我们先分析下这个类,UML图如下
1、Ordered用于决定执行顺序
2、PriorityOrdered 这个接口直接集成Ordered接口,并没有做任务扩展,只是作为一个标记接口,也用于决定BeanFactoryPostProcessor的执行顺序,在后文源码中会看到它的作用
3、Aware相关的接口我们在介绍Bean的生命周期回调时统一分析,这里暂且不管
4、FunctionalInterface java8新增的一个接口,也只是起一个标记作用,标记该接口是一个函数接口
5、BeanFactoryPostProcessor 代表这个类是一个Bean工厂的后置处理器
6、PropertiesLoaderSupport 这个类定义了属性的加载方法,包含的属性如下
//本地属性可以直接在xml中配置
@Nullable
protected Properties[] localProperties;
//是否用本地的属性覆盖提供的文件中的属性,默认不会
protected boolean localOverride = false;
//根据地址找到对应的文件
@Nullable
private Resource[] locations;
//没有找到对应文件是否抛出异常false代表不抛出
private boolean ignoreResourceNotFound = false;
//对文件资源的编码
@Nullable
private String fileEncoding;
//文件解析器
private PropertiesPersister propertiesPersister = new DefaultPropertiesPersister();
PropertyResourceConfigurer这个类主要可以对读取到的属性进行一些转换
PlaceholderConfigurerSupport 主要负责对占位符进行解析,其中几个属性如下
//默认解析的前缀
public static final String DEFAULT_PLACEHOLDER_PREFIX = "${";
//默认解析的后缀
public static final String DEFAULT_PLACEHOLDER_SUFFIX = "}";
//属性名称跟属性值的分隔符
public static final String DEFAULT_VALUE_SEPARATOR = ":";
PropertySourcesPlaceholderConfigurer 继承了上面这些类的所有功能
对这个类有些了解后,我们回到前面的例子,为什么在jdbc.property文件的属性会被应用到BasicDataSource这个bean上呢?为了帮助大家理解,我画了一个图:
这个流程如上图我们可以看到通过PropertySourcesPlaceholderConfigurer 这个特殊的BeanFactoryProcessor完成了beanDefinition中的属性值中的占位符的替换,在BeanDefinition实例化之前就进行了更改
在上图中,创建Bean的过程我们暂且不管,还有一个问题我们需要弄清楚,Spring是如何扫描并解析成BeanDefinition的呢?这里就不得不提到我们接下来需要分析的这个接口BeanDefinitionRegistryPostProcessor。
BeanDefinitionRegistryPostProcessor(重要);
我们先看一下这个接口的UML类图
从上图中,我们可以得出两个结论:
1、BeanDefinitionRegistryPostProcessor直接继承了BeanFactoryPostProcessor,所以它也是一个Bean工厂的后置处理器
2、Spring 只提供了一个内置的BeanDefinitionRegistryPostProcessor的实现类ConfigurationClassPostProcessor,实际上上面说的扫描解析成Beandefinition的过程就是这个类完成的
我们看下这个接口定义:
public interface BeanDefinitionRegistryPostProcessor extends BeanFactoryPostProcessor {
void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry var1) throws BeansException;
}
@FunctionalInterface
public interface BeanFactoryPostProcessor {
void postProcessBeanFactory(ConfigurableListableBeanFactory var1) throws BeansException;
}
相比于正常的BeanFactoryPostProcessor,BeanDefinitionRegistryPostProcessor多提供了一个方法,那么多提供的这个方法有什么用呢?这个方法在什么时候执行呢?这里我先说结论。
这个方法就是为了扩展,执行时机比BeanFactoryPostProcessor的postProcessBeanFactory这个方法更加靠前,spring利用这个特性完成了BeanDefinition的扫描解析,我们对spring扩展时也可以用这个特性,比如最新的mybatis与spring整合就是利用了这个特性。这个后面再来分析
接下来,我们分析其源码,验证上面的结论。
执行流程源码解析:
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(AppConfig.class);
这行代码的执行流程
// 1. 创建BeanFactory
// 2. 生成AnnotatedBeanDefinitionReader
// 3. 生成ClassPathBeanDefinitionScanner
this();
// 利用reader把componentClasses注册为一个BeanDefinition
register(componentClasses);
// 调用AbstractApplicationContext的refresh()方法,模板模式,会启动ApplicationContext
// 为什么叫refresh,而不叫start?
refresh();
BeanDefinitionRegistryPostProcessor的执行流程
public static void invokeBeanFactoryPostProcessors(
ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {
// Invoke BeanDefinitionRegistryPostProcessors first, if any.
Set<String> processedBeans = new HashSet<>();
//这个if基本上一定成立,除非我们手动new了一个BeanFactory
if (beanFactory instanceof BeanDefinitionRegistry) {
BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
//存储了只实现了BeanFactoryPostProcessor接口的后置处理器
List<BeanFactoryPostProcessor> regularPostProcessors = new ArrayList<>();
//存储了只实现了BeanDefinitionRegistryPostProcessor接口的后置处理器
List<BeanDefinitionRegistryPostProcessor> registryProcessors = new ArrayList<>();
// 这个beanFactoryPostProcessors集合一般情况下都是空的,除非我们手动调用容器的addBeanFactoryPostProcessor方法
for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
// BeanDefinitionRegistryPostProcessor是一个特殊的BeanFactoryPostProcessor,需要先执行postProcessBeanDefinitionRegistry方法
if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
BeanDefinitionRegistryPostProcessor registryProcessor =
(BeanDefinitionRegistryPostProcessor) postProcessor;
//执行实现了BeanDefinitionRegistryPostProcessor的postProcessBeanDefinitionRegistry方法
registryProcessor.postProcessBeanDefinitionRegistry(registry);
//保存只执行过了实现BeanDefinitionRegistryPostProcessor的postProcessBeanDefinitionRegistry方法的BeanDefinitionRegistryPostProcessor的接口
registryProcessors.add(registryProcessor);
}
else {
//保存了只实现了beanFactoryPostProcessor接口的后置处理器
regularPostProcessors.add(postProcessor);
}
}
// 保存当前需要执行的实现了BeanDefinitionRegistryPostProcessor接口的后置处理器
// Do not initialize FactoryBeans here: We need to leave all regular beans
// uninitialized to let the bean factory post-processors apply to them!
// Separate between BeanDefinitionRegistryPostProcessors that implement
// PriorityOrdered, Ordered, and the rest.
List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>();
// First, invoke the BeanDefinitionRegistryPostProcessors that implement PriorityOrdered.
// 首先,先执行实现了PriorityOrdered接口的BeanDefinitionRegistryPostProcessor的postProcessBeanDefinitionRegistry方法
String[] postProcessorNames =
beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
for (String ppName : postProcessorNames) {
// 判断这个类是否还实现了PriorityOrdered接口
if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
// 这里调用了getBean,所以生成一个BeanDefinitionRegistryPostProcessor的bean对象
//正常情况下只会有一个就是spring内置ConfigurationClassPostProcessor
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
processedBeans.add(ppName);
}
}
//根据实现的PriorityOrdered进行排序
sortPostProcessors(currentRegistryProcessors, beanFactory);
//将当前执行的currentRegistryProcessors全部添加到registryProcessors中
registryProcessors.addAll(currentRegistryProcessors);
// 执行postProcessBeanDefinitionRegistry方法 这个方法里面会进行BeanDefinition的扫描和解析
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
//清空集合
currentRegistryProcessors.clear();
// Next, invoke the BeanDefinitionRegistryPostProcessors that implement Ordered.
// 首先,先执行实现了Ordered接口的BeanDefinitionRegistryPostProcessor的postProcessBeanDefinitionRegistry方法
postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
for (String ppName : postProcessorNames) {
//确保没有被处理过并且实现了order接口
if (!processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName, Ordered.class)) {
//加入到当前需要执行的集合中
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
processedBeans.add(ppName);
}
}
//根据order接口进行排序
sortPostProcessors(currentRegistryProcessors, beanFactory);
//将需要执行的currentRegistryProcessors全部添加到registryProcessors集合里面
registryProcessors.addAll(currentRegistryProcessors);
//执行后置处理器的逻辑,这里只会执行BeanDefinitionRegistryPostProcessor的postProcessBeanDefinitionRegistry这个方法
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
//清空集合
currentRegistryProcessors.clear();
// Finally, invoke all other BeanDefinitionRegistryPostProcessors until no further ones appear.
// 最后,最后其他普通的BeanDefinitionRegistryPostProcessors的postProcessBeanDefinitionRegistry方法
boolean reiterate = true;
// 在一个BeanDefinitionRegistryPostProcessor中可以注册另一个BeanDefinitionRegistryPostProcessor,所以需要递归找出所有的BeanDefinitionRegistryPostProcessor
// 一个没有实现PriorityOrdered接口的BeanDefinitionRegistryPostProcessor如果在内部注册了一个实现了PriorityOrdered接口的BeanDefinitionRegistryPostProcessor,那么就是没有实现PriorityOrdered接口的先执行
while (reiterate) {
reiterate = false;
// 这里会再一次拿到实现了PriorityOrdered接口或Ordered接口的BeanDefinitionRegistryPostProcessor,所以需要processedBeans进行过滤
postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
for (String ppName : postProcessorNames) {
if (!processedBeans.contains(ppName)) {
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
processedBeans.add(ppName);
reiterate = true;
}
}
sortPostProcessors(currentRegistryProcessors, beanFactory);
registryProcessors.addAll(currentRegistryProcessors);
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
currentRegistryProcessors.clear();
}
// =======BeanDefinition 解析配置类(扫描,- @Bean, @Import),手动,接口, @Import
// Now, invoke the postProcessBeanFactory callback of all processors handled so far.
// 执行完BeanDefinitionRegistryPostProcessor的postProcessBeanDefinitionRegistry方法后,
// 再执行BeanDefinitionRegistryPostProcessor的postProcessBeanFactory方法
invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);
// 执行手动添加的非BeanDefinitionRegistryPostProcessor类型的Bean工厂后置处理器的postProcessBeanFactory方法
invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);
}
else {
// 如果beanFactory没有可以注册BeanDefinition的功能,则没有BeanDefinitionRegistryPostProcessor,则执行Bean工厂后置处理器的postProcessBeanFactory方法
// Invoke factory processors registered with the context instance.
invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory);
}
// 总结一下上面的流程:
// 1. 如果beanFactory实现了BeanDefinitionRegistry接口,则表示可以通过BeanDefinitionRegistryPostProcessor接口来注册BeanDefinition
// 2. 因为现在是Spring启动过程中的比较早的阶段(还没有开始扫描@Component),所以只能获取Spring默认添加到BeanFactory中的bean工厂后置处理器,以及程序员手动添加的bean工厂后置处理器
// 3. 执行的顺序是,先执行BeanDefinitionRegistryPostProcessor中的postProcessBeanDefinitionRegistry方法,因为这个方法可以注册BeanDefinition
// 4. 先执行手动添加进行来的BeanDefinitionRegistryPostProcessor的postProcessBeanDefinitionRegistry方法,这个过程中可能会向BeanFactory中注册其他的BeanDefinitionRegistryPostProcessor
// 5. 从BeanFactory中获取PriorityOrdered接口的BeanDefinitionRegistryPostProcessor,并执行postProcessBeanDefinitionRegistry方法
// 6. 从BeanFactory中获取Ordered接口的BeanDefinitionRegistryPostProcessor,并执行postProcessBeanDefinitionRegistry方法
// 7. 在5,6步中都有可能注册新的BeanDefinitionRegistryPostProcessor的
// 8. 从BeanFactory中获取普通的BeanDefinitionRegistryPostProcessor,并执行postProcessBeanDefinitionRegistry方法
// 9. 在8步中也有可能注册新的BeanDefinitionRegistryPostProcessor,所以第8步会递归,直到没有新的BeanDefinitionRegistryPostProcessor注册进来了
// 10. 在前面的步骤中都是执行BeanDefinitionRegistryPostProcessor中的postProcessBeanDefinitionRegistry方法,进行BeanDefinition的注册
// 11. BeanDefinition注册完了之后,因为BeanDefinitionRegistryPostProcessor本身也是一个BeanFactoryProcessor,所以最后再执行postProcessBeanFactory方法
// 12. 总结一句话就是:先通过BeanDefinitionRegistryPostProcessor注册BeanDefinition,再执行BeanDefinitionRegistryPostProcessor的postProcessBeanFactory方法
// 在默认情况下,上面的步骤中只有一个BeanDefinitionRegistryPostProcessor会执行,就是ConfigurationClassPostProcessor,因为它是Spring默认在添加进去的
// BeanDefinitionRegistryPostProcessor是特殊的BeanFactoryPostProcessor,在上面的逻辑中都处理完了
// 所以接下来就是处理普通的BeanFactoryPostProcessor
// Do not initialize FactoryBeans here: We need to leave all regular beans
// uninitialized to let the bean factory post-processors apply to them!
String[] postProcessorNames =
beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);
// 默认情况下会拿到两个,一个就是ConfigurationClassPostProcessor,一个就是EventListenerMethodProcessor
// Separate between BeanFactoryPostProcessors that implement PriorityOrdered,
// Ordered, and the rest.
// 保存直接实现了BeanFactoryPostProcessor接口和PriorityOrdered接口的后置处理器
List<BeanFactoryPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
// 保存直接实现了BeanFactoryPostProcessor接口和Ordered接口的后置处理器
List<String> orderedPostProcessorNames = new ArrayList<>();
// 保存直接实现了BeanFactoryPostProcessor接口的后置处理器,不包括那些实现了排序接口的类
List<String> nonOrderedPostProcessorNames = new ArrayList<>();
// 把所有BeanFactoryPostProcessor进行分类
for (String ppName : postProcessorNames) {
// 拿到的BeanFactoryPostProcessor包括了BeanDefinitionRegistryPostProcessor,所以要跳过
if (processedBeans.contains(ppName)) {
// skip - already processed in first phase above
}
else if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class));
}
else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
orderedPostProcessorNames.add(ppName);
}
else {
nonOrderedPostProcessorNames.add(ppName);
}
}
// First, invoke the BeanFactoryPostProcessors that implement PriorityOrdered.
// 先执行实现了PriorityOrdered接口的BeanFactoryPostProcessor
sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory);
// Next, invoke the BeanFactoryPostProcessors that implement Ordered.
// 再执行实现了Ordered接口的BeanFactoryPostProcessor
List<BeanFactoryPostProcessor> orderedPostProcessors = new ArrayList<>(orderedPostProcessorNames.size());
for (String postProcessorName : orderedPostProcessorNames) {
orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
}
sortPostProcessors(orderedPostProcessors, beanFactory);
invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory);
// Finally, invoke all other BeanFactoryPostProcessors.
// 最后执行普通的BeanFactoryPostProcessor
List<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList<>(nonOrderedPostProcessorNames.size());
for (String postProcessorName : nonOrderedPostProcessorNames) {
nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
}
invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory);
// 到此,所有的BeanFactoryPostProcessor都执行完了
// 对于BeanFactoryPostProcessor我们可以这么理解:它是去完善BeanFactory的,比如向BeanFactory中去注册BeanDefinition
// 就好比:BeanFactory是一张白纸,每个BeanFactoryPostProcessor都去这张白纸上去画上一笔,这个白纸就丰满了
// 所以这段代码,虽然内容很多,但是在默认情况下,主要就是执行了ConfigurationClassPostProcessor
// 1. 先执行了ConfigurationClassPostProcessor的postProcessBeanDefinitionRegistry方法,基本上就是去注册BeanDefinition
// 2. 然后执行了ConfigurationClassPostProcessor的postProcessBeanFactory方法
// Clear cached merged bean definitions since the post-processors might have
// modified the original metadata, e.g. replacing placeholders in values...
beanFactory.clearMetadataCache();
}
另外在上面的代码中大家有没有发现一个问题,当在执行postProcessBeanDefinitionRegistry方法时采用了循环的方式,不断的查找BeanDefinitionRegistryPostProcessor,就是下面的代码
boolean reiterate = true;
// 在一个BeanDefinitionRegistryPostProcessor中可以注册另一个BeanDefinitionRegistryPostProcessor,所以需要递归找出所有的BeanDefinitionRegistryPostProcessor
// 一个没有实现PriorityOrdered接口的BeanDefinitionRegistryPostProcessor如果在内部注册了一个实现了PriorityOrdered接口的BeanDefinitionRegistryPostProcessor,那么就是没有实现PriorityOrdered接口的先执行
while (reiterate) {
reiterate = false;
// 这里会再一次拿到实现了PriorityOrdered接口或Ordered接口的BeanDefinitionRegistryPostProcessor,所以需要processedBeans进行过滤
postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
for (String ppName : postProcessorNames) {
if (!processedBeans.contains(ppName)) {
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
processedBeans.add(ppName);
reiterate = true;
}
}
sortPostProcessors(currentRegistryProcessors, beanFactory);
registryProcessors.addAll(currentRegistryProcessors);
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
currentRegistryProcessors.clear();
}
但是在执行postProcessBeanFactory并没有进行类似的查找。这是为什么呢?
笔者认为主要是设计使然,Spring在设计时postProcessBeanFactory这个方法不是用于重新注册一个Bean的,而是修改,我们可以看下这个方法可以看下这个方法的java doc
/**
* Modify the application context's internal bean factory after its standard
* initialization. All bean definitions will have been loaded, but no beans
* will have been instantiated yet. This allows for overriding or adding
* properties even to eager-initializing beans.
* @param beanFactory the bean factory used by the application context
* @throws org.springframework.beans.BeansException in case of errors
*/
void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;
其中重要的一段话:All bean definitions will have been loaded,,所有的beanDefinition都已经被加载了
/**
* Modify the application context's internal bean definition registry after its
* standard initialization. All regular bean definitions will have been loaded,
* but no beans will have been instantiated yet. This allows for adding further
* bean definitions before the next post-processing phase kicks in.
* @param registry the bean definition registry used by the application context
* @throws org.springframework.beans.BeansException in case of errors
*/
void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException;
大家注意这段话 This allows for adding furtherbean definitions before the next post-processing phase kicks in.
我们允许我们在下个后置处理器执行前添加更多的beanDefinition.
从这里可以看出执行顺序来。
the bean definition registry used by the application context
* @throws org.springframework.beans.BeansException in case of errors
*/
void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException;
大家注意这段话 This allows for adding furtherbean definitions before the next post-processing phase kicks in.
我们允许我们在下个后置处理器执行前添加更多的beanDefinition.
从这里可以看出执行顺序来。