热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

深入理解SpringBeanPostProcessorInstantiationAwareBeanPostProcessor

在深入学习SpringBean生命周期一节中,我们学习了Bean后置处理器BeanPostProcessor,用于在Bean初始化前后插入我们自己的逻辑

在深入学习Spring Bean生命周期一节中,我们学习了Bean后置处理器BeanPostProcessor,用于在Bean初始化前后插入我们自己的逻辑(Bean增强,Bean代理等)。但是你知道BeanPostProcessor的子类InstantiationAwareBeanPostProcessor吗?他用于Bean实例化前后处理。

本节记录两者的区别以及简单原理分析。


1. 两者比较

Initialization为初始化的意思,Instantiation为实例化的意思。在Spring Bean生命周期中,实例化指的是创建Bean的过程,初始化指的是Bean创建后,对其属性进行赋值(populate bean)、后置处理等操作的过程,所以Instantiation执行时机先于Initialization。


1.1 类关系

先来看看BeanPostProcessor的类结构:

public interface BeanPostProcessor {// bean 初始化之前执行@Nullabledefault Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {return bean;}// bean 初始化之后执行@Nullabledefault Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {return bean;}
}

InstantiationAwareBeanPostProcessor为BeanPostProcessor的子类,新增了三个额外的方法:

public interface InstantiationAwareBeanPostProcessor extends BeanPostProcessor {&#64;Nullabledefault Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {return null;}default boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {return true;}&#64;Nullabledefault PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) throws BeansException {return null;}/** 废弃 */&#64;Deprecated&#64;Nullabledefault PropertyValues postProcessPropertyValues(PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException {return pvs;}
}

1.2 方法解析


  1. BeanPostProcessor
    • postProcessBeforeInitialization(Object bean, String beanName)&#xff1a;bean&#xff1a;Bean实例&#xff1b;beanName&#xff1a;Bean名称。方法将在Bean实例的afterPropertiesSet方法或者自定义的init方法被调用前调用&#xff0c;此时Bean属性已经被赋值。方法返回原始Bean实例或者包装后的Bean实例&#xff0c;如果返回null&#xff0c;则后续的后置处理方法不再被调用。
    • postProcessAfterInitialization(Object bean, String beanName)&#xff1a;bean&#xff1a;Bean实例&#xff1b;beanName&#xff1a;Bean名称。方法将在Bean实例的afterPropertiesSet方法或者自定义的init方法被调用后调用&#xff0c;此时Bean属性已经被赋值。方法返回原始Bean实例或者包装后的Bean实例&#xff0c;如果返回null&#xff0c;则后续的后置处理方法不再被调用。
  2. InstantiationAwareBeanPostProcessor
    • postProcessBeforeInstantiation(Class beanClass, String beanName)&#xff1a;beanClass&#xff1a;待实例化的Bean类型&#xff1b;beanName&#xff1a;待实例化的Bean名称。方法作用为&#xff1a;在Bean实例化前调用该方法&#xff0c;返回值可以为代理后的Bean&#xff0c;以此代替Bean默认的实例化过程。返回值不为null时&#xff0c;后续只会调用BeanPostProcessor的 postProcessAfterInitialization方法&#xff0c;而不会调用别的后续后置处理方法&#xff08;如postProcessAfterInitialization、postProcessBeforeInstantiation等方法&#xff09;&#xff1b;返回值也可以为null&#xff0c;这时候Bean将按默认方式初始化。
    • postProcessAfterInstantiation(Object bean, String beanName)&#xff1a;bean&#xff1a;实例化后的Bean&#xff0c;此时属性还没有被赋值&#xff1b;beanName&#xff1a;Bean名称。方法作用为&#xff1a;当Bean通过构造器或者工厂方法被实例化后&#xff0c;当属性还未被赋值前&#xff0c;该方法会被调用&#xff0c;一般用于自定义属性赋值。方法返回值为布尔类型&#xff0c;返回true时&#xff0c;表示Bean属性需要被赋值&#xff1b;返回false表示跳过Bean属性赋值&#xff0c;并且InstantiationAwareBeanPostProcessor的postProcessProperties方法不会被调用。

1.3 执行时机对比

为了验证实例化和初始化的先后顺序&#xff0c;我们直接新建一个SpringBoot项目测试即可&#xff08;我这里还使用之前的老项目&#xff09;&#xff1a;

Spring入口类名称为SpringDemoApplication。新建MyBeanPostProcessor实现BeanPostProcessor接口&#xff1a;

public class MyBeanPostProcessor implements BeanPostProcessor {&#64;Overridepublic Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {if ("springDemoApplication".equals(beanName)) {System.out.println("post processor before " &#43; beanName &#43; " initialization");}return bean;}&#64;Overridepublic Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {if ("springDemoApplication".equals(beanName)) {System.out.println("post processor after " &#43; beanName &#43; " initialization");}return bean;}}

因为对所有的Bean生效&#xff0c;所以为了方便观察输出&#xff0c;这里仅当Bean名称为springDemoApplication时才打印输出。

注册进容器中&#xff1a;

&#64;Bean
public MyBeanPostProcessor myBeanPostProcessor () {return new MyBeanPostProcessor();
}

接着新建MyBeanInstantiationPostProcessor实现InstantiationAwareBeanPostProcessor接口&#xff1a;

public class MyBeanInstantiationPostProcessor implements InstantiationAwareBeanPostProcessor {&#64;Overridepublic Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {if ("springDemoApplication".equals(beanName)) {System.out.println("post process before " &#43; beanName &#43; " instantiation");}return null;}&#64;Overridepublic boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {if ("springDemoApplication".equals(beanName)) {System.out.println("post process after " &#43; beanName &#43; " instantiation");}return true;}&#64;Overridepublic PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) throws BeansException {if ("springDemoApplication".equals(beanName)) {System.out.println("post process " &#43; beanName &#43; " properties");}return pvs;}
}

记得配置到webconfig里面。

&#64;Bean
public MyBeanInstantiationPostProcessor myBeanInstantiationPostProcessor() {return new MyBeanInstantiationPostProcessor();
}

启动程序&#xff0c;输出如下所示&#xff1a;

image-20220501210656953

如果将MyBeanInstantiationPostProcessor的postProcessAfterInstantiation方法返回值改为false&#xff0c;程序输出如下&#xff1a;

image-20220501210825737


2. 原理解析

postProcessAfterInitialization和InstantiationAwareBeanPostProcessor的方法都和Bean生命周期有关&#xff0c;要分析它们的实现原理自然要从Bean的创建过程入手。Bean创建的入口为AbstractAutowireCapableBeanFactory的createBean方法&#xff0c;查看其源码&#xff1a;

resolveBeforeInstantiation方法给Bean后置处理器一个返回目标Bean实例代理的机会&#xff0c;所以我们先重点关注下这个方法的源码。

该方法先于下面的doCreateBean方法&#xff0c;也就是说里面的操作逻辑实在Bean实例化之前完成的。

image-20220501212316509

resolveBeforeInstantiation方法源码如下所示&#xff1a;

相关注释直接标记在代码中&#xff0c;方便查看。

&#64;Nullable
protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {Object bean &#61; null;//beforeInstantiationResolved默认属性值为false,表示Bean实例化前置操作未执行if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {//判断是否有InstantiationAwareBeanPostProcessors处理器if (!mbd.isSynthetic() && this.hasInstantiationAwareBeanPostProcessors()) {Class<?> targetType &#61; this.determineTargetType(beanName, mbd);//有的话执行PostProcessorsBeforeInstantiation方法if (targetType !&#61; null) {bean &#61; this.applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);//如果上述方法返回值不为null&#xff0c;则说明Bean已经在该方法中实例化了&#xff08;代理&#xff0c;增加&#xff09;&#xff0c;那么直接执行BeanPostProcessor的PostProcessorsAfterInitialization方法if (bean !&#61; null) {bean &#61; this.applyBeanPostProcessorsAfterInitialization(bean, beanName);}}}//如果Bean不为null,则将beforeInstantiationResolved属性值设置truembd.beforeInstantiationResolved &#61; bean !&#61; null;}return bean;
}

上面方法返回的bean如果为空的话&#xff0c;AbstractAutowireCapableBeanFactory的createBean方法将继续往下执行doCreateBean方法&#xff1a;

image-20220501212946523

查看doCreateBean方法源码&#xff1a;

这个时候我们会发现这里源码很多&#xff0c;我们先不看其他部分&#xff08;Bean生命周期其他部分&#xff09;&#xff0c;重点关注populateBean和initializeBean方法。查看populateBean方法源码&#xff1a;

protected void populateBean(String beanName, RootBeanDefinition mbd, &#64;Nullable BeanWrapper bw) {if (bw &#61;&#61; null) {if (mbd.hasPropertyValues()) {throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance");}} else {if (!mbd.isSynthetic() && this.hasInstantiationAwareBeanPostProcessors()) {Iterator var4 &#61; this.getBeanPostProcessors().iterator();while(var4.hasNext()) {BeanPostProcessor bp &#61; (BeanPostProcessor)var4.next();if (bp instanceof InstantiationAwareBeanPostProcessor) {InstantiationAwareBeanPostProcessor ibp &#61; (InstantiationAwareBeanPostProcessor)bp;if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {//这个地方需要注意&#xff0c;当返回值为false的时候&#xff0c;直接返回&#xff0c;后续赋值操作不执行了return;}}}}// begin 这一块为属性赋值&#xff0c;aotowired,通过类型或者名称注入PropertyValues pvs &#61; mbd.hasPropertyValues() ? mbd.getPropertyValues() : null;int resolvedAutowireMode &#61; mbd.getResolvedAutowireMode();if (resolvedAutowireMode &#61;&#61; 1 || resolvedAutowireMode &#61;&#61; 2) {MutablePropertyValues newPvs &#61; new MutablePropertyValues((PropertyValues)pvs);if (resolvedAutowireMode &#61;&#61; 1) {this.autowireByName(beanName, mbd, bw, newPvs);}if (resolvedAutowireMode &#61;&#61; 2) {this.autowireByType(beanName, mbd, bw, newPvs);}pvs &#61; newPvs;}//end boolean hasInstAwareBpps &#61; this.hasInstantiationAwareBeanPostProcessors();boolean needsDepCheck &#61; mbd.getDependencyCheck() !&#61; 0;PropertyDescriptor[] filteredPds &#61; null;if (hasInstAwareBpps) {if (pvs &#61;&#61; null) {pvs &#61; mbd.getPropertyValues();}//属性赋值后&#xff0c;判断是否有InstantiationAwareBeanPostProcessor实例&#xff0c;有的话从缓存集合中获取遍历Iterator var9 &#61; this.getBeanPostProcessors().iterator();while(var9.hasNext()) {BeanPostProcessor bp &#61; (BeanPostProcessor)var9.next();if (bp instanceof InstantiationAwareBeanPostProcessor) {InstantiationAwareBeanPostProcessor ibp &#61; (InstantiationAwareBeanPostProcessor)bp;//逐个调用其postProcessProperties方法PropertyValues pvsToUse &#61; ibp.postProcessProperties((PropertyValues)pvs, bw.getWrappedInstance(), beanName);if (pvsToUse &#61;&#61; null) {if (filteredPds &#61;&#61; null) {filteredPds &#61; this.filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);}
//逐个调用其postProcessPropertyValues方法pvsToUse &#61; ibp.postProcessPropertyValues((PropertyValues)pvs, filteredPds, bw.getWrappedInstance(), beanName);if (pvsToUse &#61;&#61; null) {return;}}pvs &#61; pvsToUse;}}}if (needsDepCheck) {if (filteredPds &#61;&#61; null) {filteredPds &#61; this.filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);}this.checkDependencies(beanName, mbd, filteredPds, (PropertyValues)pvs);}if (pvs !&#61; null) {this.applyPropertyValues(beanName, mbd, bw, (PropertyValues)pvs);}}
}

接着查看initializeBean方法源码&#xff1a;

protected Object initializeBean(String beanName, Object bean, &#64;Nullable RootBeanDefinition mbd) {if (System.getSecurityManager() !&#61; null) {AccessController.doPrivileged(() -> {this.invokeAwareMethods(beanName, bean);return null;}, this.getAccessControlContext());} else {this.invokeAwareMethods(beanName, bean);}Object wrappedBean &#61; bean;if (mbd &#61;&#61; null || !mbd.isSynthetic()) {//执行PostProcessorsBeforeInitializationwrappedBean &#61; this.applyBeanPostProcessorsBeforeInitialization(bean, beanName);}try {this.invokeInitMethods(beanName, wrappedBean, mbd);} catch (Throwable var6) {throw new BeanCreationException(mbd !&#61; null ? mbd.getResourceDescription() : null, beanName, "Invocation of init method failed", var6);}if (mbd &#61;&#61; null || !mbd.isSynthetic()) {//执行PostProcessorsAfterInitializationwrappedBean &#61; this.applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);}return wrappedBean;
}

至此我们通过查看Bean生命周期相关源码弄清楚了BeanPostProcessor和InstantiationAwareBeanPostProcessor相关方法的执行时机以及原理。

上面源码的追踪其实不仅涉及到了BeanPostProcessor和InstantiationAwareBeanPostProcessor相关方法的执行时机以及原理&#xff0c;更是整个Bean生命周期创建过程。


3. 总结

下面通过一张流程图总结本文&#xff1a;

image-20220501212009622


推荐阅读
  • 如何使用 `org.apache.tomcat.websocket.server.WsServerContainer.findMapping()` 方法及其代码示例解析 ... [详细]
  • Android 构建基础流程详解
    Android 构建基础流程详解 ... [详细]
  • 优化后的标题:深入探讨网关安全:将微服务升级为OAuth2资源服务器的最佳实践
    本文深入探讨了如何将微服务升级为OAuth2资源服务器,以订单服务为例,详细介绍了在POM文件中添加 `spring-cloud-starter-oauth2` 依赖,并配置Spring Security以实现对微服务的保护。通过这一过程,不仅增强了系统的安全性,还提高了资源访问的可控性和灵活性。文章还讨论了最佳实践,包括如何配置OAuth2客户端和资源服务器,以及如何处理常见的安全问题和错误。 ... [详细]
  • QT框架中事件循环机制及事件分发类详解
    在QT框架中,QCoreApplication类作为事件循环的核心组件,为应用程序提供了基础的事件处理机制。该类继承自QObject,负责管理和调度各种事件,确保程序能够响应用户操作和其他系统事件。通过事件循环,QCoreApplication实现了高效的事件分发和处理,使得应用程序能够保持流畅的运行状态。此外,QCoreApplication还提供了多种方法和信号槽机制,方便开发者进行事件的定制和扩展。 ... [详细]
  • 在《Cocos2d-x学习笔记:基础概念解析与内存管理机制深入探讨》中,详细介绍了Cocos2d-x的基础概念,并深入分析了其内存管理机制。特别是针对Boost库引入的智能指针管理方法进行了详细的讲解,例如在处理鱼的运动过程中,可以通过编写自定义函数来动态计算角度变化,利用CallFunc回调机制实现高效的游戏逻辑控制。此外,文章还探讨了如何通过智能指针优化资源管理和避免内存泄漏,为开发者提供了实用的编程技巧和最佳实践。 ... [详细]
  • 基于Net Core 3.0与Web API的前后端分离开发:Vue.js在前端的应用
    本文介绍了如何使用Net Core 3.0和Web API进行前后端分离开发,并重点探讨了Vue.js在前端的应用。后端采用MySQL数据库和EF Core框架进行数据操作,开发环境为Windows 10和Visual Studio 2019,MySQL服务器版本为8.0.16。文章详细描述了API项目的创建过程、启动步骤以及必要的插件安装,为开发者提供了一套完整的开发指南。 ... [详细]
  • 本文介绍了如何利用Shell脚本高效地部署MHA(MySQL High Availability)高可用集群。通过详细的脚本编写和配置示例,展示了自动化部署过程中的关键步骤和注意事项。该方法不仅简化了集群的部署流程,还提高了系统的稳定性和可用性。 ... [详细]
  • 深入解析Android 4.4中的Fence机制及其应用
    在Android 4.4中,Fence机制是处理缓冲区交换和同步问题的关键技术。该机制广泛应用于生产者-消费者模式中,确保了不同组件之间高效、安全的数据传输。通过深入解析Fence机制的工作原理和应用场景,本文探讨了其在系统性能优化和资源管理中的重要作用。 ... [详细]
  • 在Cisco IOS XR系统中,存在提供服务的服务器和使用这些服务的客户端。本文深入探讨了进程与线程状态转换机制,分析了其在系统性能优化中的关键作用,并提出了改进措施,以提高系统的响应速度和资源利用率。通过详细研究状态转换的各个环节,本文为开发人员和系统管理员提供了实用的指导,旨在提升整体系统效率和稳定性。 ... [详细]
  • 本指南介绍了如何在ASP.NET Web应用程序中利用C#和JavaScript实现基于指纹识别的登录系统。通过集成指纹识别技术,用户无需输入传统的登录ID即可完成身份验证,从而提升用户体验和安全性。我们将详细探讨如何配置和部署这一功能,确保系统的稳定性和可靠性。 ... [详细]
  • 本文深入解析了WCF Binding模型中的绑定元素,详细介绍了信道、信道管理器、信道监听器和信道工厂的概念与作用。从对象创建的角度来看,信道管理器负责信道的生成。具体而言,客户端的信道通过信道工厂进行实例化,而服务端则通过信道监听器来接收请求。文章还探讨了这些组件之间的交互机制及其在WCF通信中的重要性。 ... [详细]
  • Python 伦理黑客技术:深入探讨后门攻击(第三部分)
    在《Python 伦理黑客技术:深入探讨后门攻击(第三部分)》中,作者详细分析了后门攻击中的Socket问题。由于TCP协议基于流,难以确定消息批次的结束点,这给后门攻击的实现带来了挑战。为了解决这一问题,文章提出了一系列有效的技术方案,包括使用特定的分隔符和长度前缀,以确保数据包的准确传输和解析。这些方法不仅提高了攻击的隐蔽性和可靠性,还为安全研究人员提供了宝贵的参考。 ... [详细]
  • 在使用 Qt 进行 YUV420 图像渲染时,由于 Qt 本身不支持直接绘制 YUV 数据,因此需要借助 QOpenGLWidget 和 OpenGL 技术来实现。通过继承 QOpenGLWidget 类并重写其绘图方法,可以利用 GPU 的高效渲染能力,实现高质量的 YUV420 图像显示。此外,这种方法还能显著提高图像处理的性能和流畅性。 ... [详细]
  • 本文探讨了在任务完成后将其转换为最终状态时的异常处理机制。通过分析 `TaskCompletionSource` 的使用场景,详细阐述了其在异步编程中的重要作用,并提供了具体的实现方法和注意事项,帮助开发者更好地理解和应用这一技术。 ... [详细]
  • 本文将继续探讨 JavaScript 函数式编程的高级技巧及其实际应用。通过一个具体的寻路算法示例,我们将深入分析如何利用函数式编程的思想解决复杂问题。示例中,节点之间的连线代表路径,连线上的数字表示两点间的距离。我们将详细讲解如何通过递归和高阶函数等技术实现高效的寻路算法。 ... [详细]
author-avatar
KJ慧兒H妹子Ed
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有