Spring扩展接口(4):InstantiationAwareBeanPostProcessor
在此系列文章中,我总结了Spring几乎所有的扩展接口,以及各个扩展点的使用场景。并整理出一个bean在spring中从被加载到最终初始化的所有可扩展点的顺序调用图。这样,我们也可以看到bean是如何一步步加载到spring容器中的。

InstantiationAwareBeanPostProcessor
1、概述
public interface InstantiationAwareBeanPostProcessor extends BeanPostProcessor {
@Nullable
default Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
return null;
} default boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
return true;
} @Nullable
default PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) throws BeansException {
return null;
}
}
Spring框架提供了许多扩展接口,用于在Bean的生命周期中插入自定义逻辑。其中之一是InstantiationAwareBeanPostProcessor接口,它允许我们在Spring容器实例化Bean之前和之后进行一些自定义处理。
InstantiationAwareBeanPostProcessor接口是BeanPostProcessor接口的子接口,它定义了在Bean实例化过程中的扩展点。与BeanPostProcessor接口相比,InstantiationAwareBeanPostProcessor接口提供了更细粒度的控制能力。它在Bean实例化的不同阶段提供了多个回调方法,允许我们在不同的时机对Bean进行自定义处理。
在Spring容器启动过程中,InstantiationAwareBeanPostProcessor接口的方法执行顺序如下:
- postProcessBeforeInstantiation方法:在Bean实例化之前调用,如果返回null,一切按照正常顺序执行,如果返回的是一个实例的对象,那么这个将会跳过实例化、初始化的过程
- postProcessAfterInstantiation方法:在Bean实例化之后调用,可以对已实例化的Bean进行进一步的自定义处理。
- postProcessPropertyValues方法:在Bean的属性注入之前调用,可以修改Bean的属性值或进行其他自定义操作,当postProcessAfterInstantiation返回true才执行。
| 方法 | 执行顺序 | 备注 |
|---|---|---|
| postProcessBeforeInstantiation() | 在 Bean 创建前调用 | 可用于创建代理类,如果返回的不是 null(也就是返回的是一个代理类) ,那么后续只会调用 postProcessAfterInitialization() 方法 |
| postProcessAfterInstantiation() | 在 Bean 创建后调用 | 返回值会影响 postProcessProperties() 是否执行,其中返回 false 的话,是不会执行。 |
| postProcessProperties() | 在 Bean 设置属性前调用 | 用于修改 bean 的属性,如果返回值不为空,那么会更改指定字段的值 |
2、简单案例
下面是一个示例,演示了TestUser这个Bean内部的执行流程。
// InstantiationAwareBeanPostProcessor扩展实现
@Component
public class MyInstantiationAwareBeanPostProcessor implements InstantiationAwareBeanPostProcessor {
@Override
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
if(isMatchClass(beanClass)){
System.out.println("调用 postProcessBeforeInstantiation 方法");
}
return null;
}
@Override
public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
if(isMatchClass(bean.getClass())){
System.out.println("调用 postProcessAfterInstantiation 方法");
}
return true;
}
@Override
public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) throws BeansException {
if(isMatchClass(bean.getClass())){
System.out.println("调用 postProcessProperties 方法");
}
return pvs;
}
private boolean isMatchClass(Class<?> beanClass){
return TestUser.class.equals(ClassUtils.getUserClass(beanClass));
}
}
// TestUser测试类
@Component
public class TestUser implements InitializingBean {
String name;
String password;
public TestUser() {
System.out.println("创建【TestUser】对象");
}
public String getName() {
return name;
}
public void setName(String name) {
System.out.println("设置【name】属性");
this.name = name;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
System.out.println("设置【password】属性");
this.password = password;
}
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("所有属性设置完毕");
}
}
输出:
调用 postProcessBeforeInstantiation 方法
创建【TestUser】对象
调用 postProcessAfterInstantiation 方法
调用 postProcessProperties 方法
所有属性设置完毕
3、源码分析
InstantiationAwareBeanPostProcessor是在对象实例化和初始化前后执行的逻辑,因此主要的代码都在getBean,doGetBean,cerateBean方法中。
- 在MyBeanFactoryPostProcessor打上断点,启动SpringApplication,可以看到左下角的调用链路。

- spring的AbstractApplicationContext的refresh方法,执行this.onRefresh()。

- 在实例化之前,调用postProcessBeforeInstantiation方法入口就在this.resolveBeforeInstantiation(beanName, mbdToUse)中。


- bean = this.applyBeanPostProcessorsBeforeInstantiation(targetType, beanName)中遍历InstantiationAwareBeanPostProcessor的postProcessBeforeInstantiation方法。
- 若 this.applyBeanPostProcessorsBeforeInstantiation(targetType, beanName)返回了已实例化的Bean,则执行调用postProcessAfterInitialization方法。

- 在执行完resolveBeforeInstantiation()后,调用doCreateBean()。
- 在doCreateBean()中先实例化Bean,再调用populateBean()执行后续的postProcessAfterInstantiation()和postProcessProperties()。





Spring扩展接口(4):InstantiationAwareBeanPostProcessor的更多相关文章
- Spring8:一些常用的Spring Bean扩展接口
前言 Spring是一款非常强大的框架,可以说是几乎所有的企业级Java项目使用了Spring,而Bean又是Spring框架的核心. Spring框架运用了非常多的设计模式,从整体上看,它的设计严格 ...
- 0001 - Spring 框架和 Tomcat 容器扩展接口揭秘
前言 在 Spring 框架中,每个应用程序上下文(ApplicationContext)管理着一个 BeanFactory,BeanFactory 主要负责 Bean 定义的保存.Bean 的创建. ...
- 深入理解Spring系列之八:常用的扩展接口
转载 https://mp.weixin.qq.com/s/XfhZltSlTall8wKwV_7fKg Spring不仅提供了一个进行快速开发的基础框架,而且还提供了很多可扩展的接口,用于满足一些额 ...
- spring源码分析系列 (3) spring拓展接口InstantiationAwareBeanPostProcessor
更多文章点击--spring源码分析系列 主要分析内容: 一.InstantiationAwareBeanPostProcessor简述与demo示例 二.InstantiationAwareBean ...
- spring初始化源码浅析之关键类和扩展接口
目录 1.关键接口和类 1.1.关键类之 DefaultListableBeanFactory 1.2.关键类之XmlBeanDefinitionReader 1.3.关键类之ClassPathXml ...
- spring扩展点整理
本文转载自spring扩展点整理 背景 Spring的强大和灵活性不用再强调了.而灵活性就是通过一系列的扩展点来实现的,这些扩展点给应用程序提供了参与Spring容器创建的过程,好多定制化的东西都需要 ...
- spring源码分析系列 (2) spring拓展接口BeanPostProcessor
Spring更多分析--spring源码分析系列 主要分析内容: 一.BeanPostProcessor简述与demo示例 二.BeanPostProcessor源码分析:注册时机和触发点 (源码基于 ...
- spring扩展点之三:Spring 的监听事件 ApplicationListener 和 ApplicationEvent 用法,在spring启动后做些事情
<spring扩展点之三:Spring 的监听事件 ApplicationListener 和 ApplicationEvent 用法,在spring启动后做些事情> <服务网关zu ...
- spring扩展点之二:spring中关于bean初始化、销毁等使用汇总,ApplicationContextAware将ApplicationContext注入
<spring扩展点之二:spring中关于bean初始化.销毁等使用汇总,ApplicationContextAware将ApplicationContext注入> <spring ...
- PHP安装memcache扩展接口步骤
1.将php_memcache.dll文件保存到php的应用程序扩展ext目录中 2.在php.ini配置文件添加扩展的位置,加入一行extension=php_memcache.dll 3.重新启动 ...
随机推荐
- Failed to connect to 127.0.0.1 port 1080: Connection refused拒绝连接错误
一.git拒绝连接原因分析 使用git从远程仓库下载代码出现上述的错误是因为使用了proxy代理,所以要解决该问题,核心操作就是要取消代理 二.解决方式 1.查看Linux当前有没有使用代理 通过gi ...
- LeetCode 周赛上分之旅 #33 摩尔投票派上用场
️ 本文已收录到 AndroidFamily,技术和职场问题,请关注公众号 [彭旭锐] 和 [BaguTree Pro] 知识星球提问. 学习数据结构与算法的关键在于掌握问题背后的算法思维框架,你的思 ...
- Pandas:获取Dataframe索引
解决方案 效果图 参考链接 https://blog.csdn.net/YENTERTAINR/article/details/109254583
- React: React-Router嵌套路由 exact问题
说明 当使用嵌套路由时,不能在父路由中添加exact,因为要先匹配父路由才能匹配子路由 父路由 子路由 效果如下所示 参考链接 https://www.jianshu.com/p/8bc3251079 ...
- LeetCode 周赛上分之旅 # 36 KMP 字符串匹配殊途同归
️ 本文已收录到 AndroidFamily,技术和职场问题,请关注公众号 [彭旭锐] 和 BaguTree Pro 知识星球提问. 学习数据结构与算法的关键在于掌握问题背后的算法思维框架,你的思考越 ...
- 《深入理解Java虚拟机》读书笔记:HotSpot虚拟机对象探秘
基于实用优先的原则,以常用的虚拟机HotSpot和常用的内存区域Java堆为例,深入探讨HotSpot虚拟机在Java堆中对象分配.布局和访问的全过程.以下是本节内容的脑图. HotSpot虚拟机对象 ...
- AI 一键去水印:教你无限量使用商业图片的技巧
场景再现 刚开始注册账号(啥账号具体不表了,小编不喜欢的那个),想弄个闪亮,好看,有个性化的 Logo.作为一名非专美工小白人员,网上翻了很久作图工具,要么就是不好用,好用的大部分都收费.最后没办法, ...
- 《深入理解Java虚拟机》读书笔记: 类加载器
类加载器 虚拟机设计团队把类加载阶段中的"通过一个类的全限定名来获取描述 ...
- 知识图谱(Knowledge Graph)- Neo4j 5.10.0 使用 - Python 操作
数据基于: 知识图谱(Knowledge Graph)- Neo4j 5.10.0 使用 - CQL - 太极拳传承谱系表 这是一个非常简单的web应用程序,它使用我们的Movie图形数据集来提供列表 ...
- 《SQL与数据库基础》22. 分库分表(二)
目录 分库分表(二) MyCat分片规则 范围分片 取模分片 一致性hash分片 枚举分片 应用指定算法 固定分片hash算法 字符串hash解析 按天分片 自然月分片 MyCat原理 MyCat管理 ...