【spring源码分析】IOC容器初始化——查漏补缺(二)
前言:在【spring源码分析】IOC容器初始化(八)中多次提到了前置处理与后置处理,本篇文章针对此问题进行分析。Spring对前置处理或后置处理主要通过BeanPostProcessor进行实现。
BeanPostProcessor的作用:在Bean实例化前后,如果需要对Bean进行一些配置、增加一些自己的处理逻辑,则使用BeanPostProcessor。
BeanPostProcessor示例
定义一个类实现BeanPostProcessor接口:
public class UserDefinedBeanPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println("BeanName=" + beanName + " 初始化之前进入");
if ("beanPostProcessorBase".equals(beanName)) {
BeanPostProcessorBase processorBase = (BeanPostProcessorBase) bean;
processorBase.setMsg("Hello BeanPostProcessor!!!!!!!");
}
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println("BeanName=" + beanName + " 初始化之后进入");
return bean;
}
public void showMsg() {
System.out.println("BeanPostProcessor Test!!!!!!");
}
}
再定义一个基础测试类:
public class BeanPostProcessorBase {
private String msg;
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
}
测试方法:
@Test
public void beanPostProcessorTest() {
ApplicationContext context = new ClassPathXmlApplicationContext("com/dev/config/beanpostprocessor/beanpostprocessor.xml");
BeanPostProcessorBase postProcessor = context.getBean(BeanPostProcessorBase.class);
System.out.println(postProcessor.getMsg());
}
运行结果:

分析:
首先必须明确BeanPostProcessor的执行时机:AbstractAutowireCapableBeanFactory#initializeBean方法
protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {
// 安全模式
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
// 激活Aware方法,对特殊bean处理:Aware、BeanClassLoaderAware、BeanFactoryAware
invokeAwareMethods(beanName, bean);
return null;
}, getAccessControlContext());
} else {
// 非安全模式下激活Aware方法,对特殊bean处理:Aware、BeanClassLoaderAware、BeanFactoryAware
invokeAwareMethods(beanName, bean);
}
// 后置处理器 before
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);
}
// 后置处理器 after
if (mbd == null || !mbd.isSynthetic()) {
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
return wrappedBean;
}
分析:
- 从该函数逻辑可以看出,BeanPostProcessor的执行时机是在bean初始化前后,其实这里也可以看出bean的生命周期,这里后面再分析。
- 还有为什么要创建一个基础测试类来进行演示,如果直接使用UserDefinedBeanPostProcessor类进行演示是得不到我们所需要的效果的,因为ApplicationContext对象会自动注册BeanPostProcessor,并且在注册会实例化BeanPostProcessor,然后在第二次调用的时候就会从单例缓存中取值,因此得不到想要的效果。自动注册并实例化BeanPostProcessor参看PostProcessorRegistrationDelegate#registerBeanPostProcessors函数,细读该函数就会豁然开朗。
BeanPostProcessor总结
BeanPostProcessor可以理解为是Spring的一个工厂钩子(其实Spring提供一系列的钩子,如Aware 、InitializingBean、DisposableBean),它是Spring提供的对象实例化阶段强有力的扩展点,允许Spring在实例化bean阶段对其进行定制化修改,比较常见的使用场景是处理标记接口实现类或者为当前对象提供代理实现(例如 AOP)。
BeanPostProcessor的执行时机如下:

注意:一般的BeanFactory是不支持自动注册BeanPostProcessor,需手动调用addBeanPostProcessor进行注册,但是ApplicationContext支持自动注册,但是在其注册过程中就会对BeanPostProcessor进行初始化并进缓存,因此在示例代码中利用了基础测试类来进行演示。
BeanPostProcessor的作用域是容器级别的,它只和所在的容器相关,当BeanPostProcessor完成注册后,它会应用于所有跟它在同一容器内的bean。
by Shawn Chen,2019.05.05,上午。
【spring源码分析】IOC容器初始化——查漏补缺(二)的更多相关文章
- 【spring源码分析】IOC容器初始化——查漏补缺(一)
前言:在[spring源码分析]IOC容器初始化(十一)中提到了初始化bean的三个步骤: 激活Aware方法. 后置处理器应用(before/after). 激活自定义的init方法. 这里我们就来 ...
- 【spring源码分析】IOC容器初始化——查漏补缺(五)
前言:我们知道在Spring中经常使用配置文件的形式对进行属性的赋值,那配置文件的值是怎么赋值到属性上的呢,本文将对其进行分析. 首先了解一个类:PropertySourcesPlaceholderC ...
- 【spring源码分析】IOC容器初始化——查漏补缺(四)
前言:在前几篇查漏补缺中,其实我们已经涉及到bean生命周期了,本篇内容进行详细分析. 首先看bean实例化过程: 分析: bean实例化开始后 注入对象属性后(前面IOC初始化十几篇文章). 检查激 ...
- SPRING源码分析:IOC容器
在Spring中,最基本的IOC容器接口是BeanFactory - 这个接口为具体的IOC容器的实现作了最基本的功能规定 - 不管怎么着,作为IOC容器,这些接口你必须要满足应用程序的最基本要求: ...
- 【spring源码分析】IOC容器初始化——查漏补缺(三)
前言:本文分析InitializingBean和init-method方法,其实该知识点在AbstractAutowireCapableBeanFactory#initializeBean方法中有所提 ...
- Spring源码解析-ioc容器的设计
Spring源码解析-ioc容器的设计 1 IoC容器系列的设计:BeanFactory和ApplicatioContext 在Spring容器中,主要分为两个主要的容器系列,一个是实现BeanFac ...
- spring源码分析---IOC(1)
我们都知道spring有2个最重要的概念,IOC(控制反转)和AOP(依赖注入).今天我就分享一下spring源码的IOC. IOC的定义:直观的来说,就是由spring来负责控制对象的生命周期和对象 ...
- spring 源码之 ioc 容器的初始化和注入简图
IoC最核心就是两个过程:IoC容器初始化和IoC依赖注入,下面通过简单的图示来表述其中的关键过程:
- Spring 源码剖析IOC容器(一)概览
目录 一.容器概述 二.核心类源码解读 三.模拟容器获取Bean ======================= 一.容器概述 spring IOC控制反转,又称为DI依赖注入:大体是先初始化bean ...
随机推荐
- IE6图片透明问题
网上很多解决IE6下png透明问题的方案,但是经本人实践,有的时候有用,有的时候并不能解决自己的问题.当是后者的时候,想到另外一种办法,就是当在IE6.IE7下使用gif图片,自己在测试的时候,如果g ...
- TypeScript入门九:TypeScript的模块
关于TypeScript模块的基本使用方法 Ts的模块化语法与ES6的语法基本是一致(关于一些细节特性没有测试,请各自自行测试),然后再由tsconfig.json的module字段来描述转码类型,具 ...
- Struts2系列漏洞起始篇
前言 到目前位置struts2的漏洞编号已经到了S2-057,一直想系统的学习下Struts2的漏洞,但由于工作量较大,一直搁浅.最近由于工作需要,借此机会来填下坑.个人认为一个框架漏洞出来了仅仅看下 ...
- java入门学习总结_04
1.循环结构 2.方法 循环结构 概述 1.对于某些需要重复执行的,相同或者相似的语句,使用某种格式来完成对代码的简化. 2.实现的语句: for语句[常用] while语句[常用] do...whi ...
- adb使用时出现unanthorized问题
adb使用时出现unanthorized问题 ADB 启动时,adb devices出现unanthorized问题. 检查USB调试是否开启. 重新拔插USB数据线是否有授权提示 重启adb :ad ...
- 关于js里的布尔值判断
第一种if(a)a为以下值时转换为false false undefined null 0 -0 NaN ""
- markdown编辑器抉择经历(做笔记\多系统用户)
之前一段时间,为了找到一款合适的md编辑器可谓是费尽了心思,用了我不少时间才找到一款合适的跨平台的又美观方便的编辑器----马克飞象. 感觉虽然有些编辑器功能很强大,对于使用性单一的用户,比如像我这种 ...
- python-----将图片与标注的xml坐标水平翻转
我们做机器学习的时候,总会用到很多训练集,然后我们的数据比较少的时候,就可以将图片翻转标注.代码如下: #!/usr/bin/env python # -*- coding: utf-8 -*- # ...
- Linux下的帮助命令(man/help/info)
1.man 帮助命令 用法 man(选项)(参数) 选项 -a:在所有的man帮助手册中搜索: -f:等价于whatis指令,显示给定关键字的简短描述信息: -P:指定内容时使用分页程序: -M:指定 ...
- Auth2.0 例子【转载】
本文转载自:https://www.cnblogs.com/flashsun/p/7424071.html 1.引言 本篇文章是介绍OAuth2.0中最经典最常用的一种授权模式:授权码模式 非常简单的 ...