Spring ApplicationContext(六)BeanPostProcessor
Spring ApplicationContext(六)BeanPostProcessor
产生回顾一下 ApplicationContext 初始化的几个步骤:第一步是刷新环境变量;第二步是刷新 beanFactory 并加载 BeanDefinition;第三步是对 beanFactory 进行功能扩展,如增加 SPEL 支持和属性编辑器;第四步是留给子类实现的。
上一节中向 Spring 中注册将执行了 BeanFactoryPostProcessor,本节则继续探讨一下 BeanPostProcessor 的注册及调用时机。
public interface BeanPostProcessor {
// 在初始化之前调用
Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException;
// 在初始化之后调用
Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException;
}
- BeanPostProcessor 什么时候注册?
BeanFactory 和 ApplicationContext 容器的注册方式不大一样:若使用 BeanFactory,则必须要显示的调用其 addBeanPostProcessor() 方法进行注册;如果是使用 ApplicationContext,那么容器会在配置文件在中自动寻找实现了 BeanPostProcessor 接口的 Bean,然后自动注册。
- BeanPostProcessor 如何确保调用顺序?
假如我们使用了多个的 BeanPostProcessor 的实现类,那么如何确定处理顺序呢?其实只要实现 Ordered 接口,设置 order 属性就可以很轻松的确定不同实现类的处理顺序了;
接口中的两个方法都要将传入的 bean 返回,而不能返回 null,如果返回的是 null 那么我们通过 getBean() 方法将得不到目标。
一、BeanPostProcessor 的注册
源代码【AbstractApplicationContext】
@Override
public void refresh() throws BeansException, IllegalStateException {
// 6. 注册 BeanPostProcessor 后置处理器,在 getBean() 创建 bean 时调用
registerBeanPostProcessors(beanFactory);
/**
* 1. 实例化剩余的所有非延迟加载单例对象
* 2. 为什么说是剩余的?因为在上面的 registerBeanPostProcessors 中已经把所有 BeanPostProcessors 所有对象都已经实例化过了;
* 3. 这加载的时候会判断 bean 是不是 FactoryBean 类型的
* 3.1 如果是 FactoryBean 类型,则 getBean(&beanName),这里是把 FactoryBean 本身的对象给实例化了,而没有调它的 getObject 方法;
* 3.2 如果不是 FactoryBean 类型,直接 getBean() 就行了;
* 4. 还要判断是不是 SmartInitializingSingleton 接口,这个接口有个 afterSingletonsInstantiated 方法;
*/
finishBeanFactoryInitialization(beanFactory);
}
protected void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory) {
PostProcessorRegistrationDelegate.registerBeanPostProcessors(beanFactory, this);
}
源代码【PostProcessorRegistrationDelegate】
public static void registerBeanPostProcessors(
ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext) {
// 1. 此时 BeanDefinition 已经加载,只是 bean 还没有被实例化
String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);
// 2. 记录日志用
// 可能已经注册了部分 BeanFactoryPostProcessors 接口
int beanProcessorTargetCount = beanFactory.getBeanPostProcessorCount() + 1 + postProcessorNames.length;
beanFactory.addBeanPostProcessor(new BeanPostProcessorChecker(beanFactory, beanProcessorTargetCount));
// 3. 按 PriorityOrdered internal Ordered nonOrdered 四个级别
// 3.1 优先级最高的 BeanPostProcessors,这类最先调用;需要实现 PriorityOrdered 接口
List<BeanPostProcessor> priorityOrderedPostProcessors = new ArrayList<BeanPostProcessor>();
// 3.2 内部 BeanPostProcessors
List<BeanPostProcessor> internalPostProcessors = new ArrayList<BeanPostProcessor>();
// 3.3 继承了 Ordered 接口,优先级比上面低一点
List<String> orderedPostProcessorNames = new ArrayList<String>();
// 3.4 这就是普通的了,优先级最低
List<String> nonOrderedPostProcessorNames = new ArrayList<String>();
for (String ppName : postProcessorNames) {
if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
priorityOrderedPostProcessors.add(pp);
if (pp instanceof MergedBeanDefinitionPostProcessor) {
internalPostProcessors.add(pp);
}
}
else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
orderedPostProcessorNames.add(ppName);
}
else {
nonOrderedPostProcessorNames.add(ppName);
}
}
// 4. PriorityOrdered internal Ordered nonOrdered 分别排序、初始化、注册
// 4.1 PriorityOrdered BeanPostProcessors
sortPostProcessors(beanFactory, priorityOrderedPostProcessors);
registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors);
// 4.2 Ordered BeanPostProcessors
List<BeanPostProcessor> orderedPostProcessors = new ArrayList<BeanPostProcessor>();
for (String ppName : orderedPostProcessorNames) {
BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
orderedPostProcessors.add(pp);
if (pp instanceof MergedBeanDefinitionPostProcessor) {
internalPostProcessors.add(pp);
}
}
sortPostProcessors(beanFactory, orderedPostProcessors);
registerBeanPostProcessors(beanFactory, orderedPostProcessors);
// 4.3 nonOrdered BeanPostProcessors
List<BeanPostProcessor> nonOrderedPostProcessors = new ArrayList<BeanPostProcessor>();
for (String ppName : nonOrderedPostProcessorNames) {
BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
nonOrderedPostProcessors.add(pp);
if (pp instanceof MergedBeanDefinitionPostProcessor) {
internalPostProcessors.add(pp);
}
}
registerBeanPostProcessors(beanFactory, nonOrderedPostProcessors);
// 4.4 internal BeanPostProcessors
// 注意重复注册会先删除先注册的元素加添加到集合最后面,影响执行顺序
sortPostProcessors(beanFactory, internalPostProcessors);
registerBeanPostProcessors(beanFactory, internalPostProcessors);
beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(applicationContext));
}
private static void registerBeanPostProcessors(
ConfigurableListableBeanFactory beanFactory, List<BeanPostProcessor> postProcessors) {
for (BeanPostProcessor postProcessor : postProcessors) {
beanFactory.addBeanPostProcessor(postProcessor);
}
}
源代码【AbstractBeanFactory】
private final List<BeanPostProcessor> beanPostProcessors = new ArrayList<BeanPostProcessor>();
@Override
public void addBeanPostProcessor(BeanPostProcessor beanPostProcessor) {
Assert.notNull(beanPostProcessor, "BeanPostProcessor must not be null");
// 如果已经注册则删除后重新注册,影响其执行顺序,如 internal 中的 MergedBeanDefinitionPostProcessor
this.beanPostProcessors.remove(beanPostProcessor);
this.beanPostProcessors.add(beanPostProcessor);
if (beanPostProcessor instanceof InstantiationAwareBeanPostProcessor) {
this.hasInstantiationAwareBeanPostProcessors = true;
}
if (beanPostProcessor instanceof DestructionAwareBeanPostProcessor) {
this.hasDestructionAwareBeanPostProcessors = true;
}
}
总结:
(1) 最后 BeanPostProcessor 的注册顺序为 PriorityOrdered、Ordered、nonOrdered、internal,其中 internal 又分为 PriorityOrdered、Ordered、nonOrdered 三种顺序。
二、BeanPostProcessor 实战
class PriorityOrderTest implements BeanPostProcessor, PriorityOrdered {}
class OrderTest implements BeanPostProcessor, Ordered {}
class NoneTest implements BeanPostProcessor {}
三、BeanPostProcessor 调用时机
源代码【AbstractAutowireCapableBeanFactory】
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args) {
//省略...
populateBean(beanName, mbd, instanceWrapper);
if (exposedObject != null) {
// BeanPostProcessors 两个方法都在这里面
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
}
protected Object initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) {
// 省略 ...
invokeAwareMethods(beanName, bean);
Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
// 初始化前
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}
try {
// 初始化
invokeInitMethods(beanName, wrappedBean, mbd);
}
catch (Throwable ex) {
throw new BeanCreationException(
(mbd != null ? mbd.getResourceDescription() : null),
beanName, "Invocation of init method failed", ex);
}
if (mbd == null || !mbd.isSynthetic()) {
// 初始化后
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
return wrappedBean;
}
@Override
public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)
throws BeansException {
Object result = existingBean;
for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
result = beanProcessor.postProcessBeforeInitialization(result, beanName);
if (result == null) {
return result;
}
}
return result;
}
每天用心记录一点点。内容也许不重要,但习惯很重要!
Spring ApplicationContext(六)BeanPostProcessor的更多相关文章
- Spring ApplicationContext(一)初始化过程
Spring 容器 ApplicationContext(一)初始化过程 Spring 系列目录(https://www.cnblogs.com/binarylei/p/10198698.html) ...
- Spring ApplicationContext(五)invokeBeanFactoryPostProcessors
Spring ApplicationContext(六)BeanPostProcessor 产生回顾一下 ApplicationContext 初始化的几个步骤:第一步是刷新环境变量:第二步是刷新 b ...
- Spring中的BeanPostProcessor详解
Spring中的BeanPostProcessor详解 概述 BeanPostProcessor也称为Bean后置处理器,它是Spring中定义的接口,在Spring容器的创建过程中(具体为Bean初 ...
- 以静态变量保存 Spring ApplicationContext
package com.thinkgem.jeesite.common.utils; import java.net.HttpURLConnection; import java.net.URL; i ...
- Spring Boot(六):如何使用mybatis
Spring Boot(六):如何使用mybatis orm框架的本质是简化编程中操作数据库的编码,发展到现在基本上就剩两家了,一个是宣称可以不用写一句SQL的hibernate,一个是可以灵活调试动 ...
- Spring ApplicationContext(二)环境准备
Spring ApplicationContext(二)环境准备 Spring 系列目录(https://www.cnblogs.com/binarylei/p/10198698.html) 本节介绍 ...
- Spring ApplicationContext(八)事件监听机制
Spring ApplicationContext(八)事件监听机制 本节则重点关注的是 Spring 的事件监听机制,主要是第 8 步:多播器注册:第 10 步:事件注册. public void ...
- Spring点滴六:Spring中定义bean的继承
在基于XML配置元数据中,bean标签可以包含很多配置信息,可以包含构造函数的参数,属性值以及其他一些初始化方法.子bean的定义可以继承父bean定义元数据,子bean定义可以根据需要重写父bean ...
- Caused by: java.io.FileNotFoundException: Could not open ServletContext resource [/config/spring/applicationContext.xml]
在搭建SpringMVC框架的时候遇到了这个问题 问题的原因: 就是没有找到applicatoincontext.xml这个文件, 因为idea自动生成的路径不正确 因此需要再web.xml里面, ( ...
随机推荐
- React Mixins
[React Mixins] ES6 launched without any mixin support. Therefore, there is no support for mixins whe ...
- 解题6(OutputNMin)
题目描述 输入n个整数,输出其中最小的k个. 详细描述: 接口说明 原型: bool GetMinK(unsignedint uiInputNum, int * pInputArray, unsign ...
- struts2前后台传值的三种方法
原文地址: http://laokaddk.blog.51cto.com/368606/1340816 多的不说,直接上代码; struts.xml代码: <?xml version=" ...
- redis主从复制踩到的那些坑
一.报错:* MASTER <-> SLAVE sync started # Error condition on socket for SYNC: No route to host解决: ...
- 基本数据类型(dict)
05. 基本数据类型(dict)内容:1. 字典的简单介绍2. 字典增删改查和其他操作3. 字典的嵌套⼀. 字典的简单介绍字典(dict)是python中唯⼀的⼀个映射类型.他是以{ }括起来的键值对 ...
- jquery 事件委托(利用冒泡)
将事件绑定在父元素上,格式$(父元素).on("事件名称","子元素选择器",function(方法体){}) <!DOCTYPE html> &l ...
- Properties 使用
Properties 属于Map 下HashTable的小弟 属于持久的属性集,他可以保存在流中或者在流中加载. 键和值都是字符串类型. 通常用于配置文件 方法介绍: 存放键值对:setPropert ...
- IIS挂起网站配置文件地址
“C/用户/Administrator/我的文档/IISExpress/Config/applicationhost”
- shell脚本小集锦
1) 如何向脚本传递参数 ? ./script argument 例子: 显示文件名称脚本 ./show.sh file1.txt cat show.sh #!/bin/bash 2) 如何在脚本中使 ...
- css常见问题一
[1]禁止换行.class {word-break:keep-all;white-space:nowrap;}[2]强制换行.class{word-break:break-all;}普通容器中(Div ...