聚焦Spring后置处理器分析对比

目录

一、理解Spring后置处理器

二、Spring后置处理器在IOC容器和bean对象生命周期的切入时机分析

(一)IOC 容器生命周期中的切入时机

(二)Bean 对象生命周期中的切入时机

三、BeanPostProcessor后置器分析

(一)源码分析

(二)具体切入时机分析

(三)InstantiationAwareBeanPostProcessor派生分析

(四)DestructionAwareBeanPostProcessor派生分析

(五)MergeBeanDefinitionPostProcessor

四、BeanFactoryPostProcessor后置器分析

(一)源码展示

(二)切入时机说明

(三)BeanDefinitionRegistryPostProcessor派生分析

五、Spring后置处理器对比分析

 源码或官方文章


Spring Framework 中的后置处理器允许在容器实例化 Bean 或者在 Bean 的生命周期中进行操作。从源码上来看的话,其实其扩展机制下的后置处理器其实很多。我们重点放到我们常用的几个上BeanPostProcessor、BeanFactoryPostProcessor来聚焦分析一下。

一、理解Spring后置处理器

提供一种灵活的机制,允许开发人员在 Spring 容器管理的 Bean 生命周期的不同阶段插入自定义的逻辑,从而实现各种需求。注意官方文档中并未直接提及 "Spring 后置处理器" 这个术语,但是从文档中可以看出 Spring 框架提供了一系列的扩展点和接口,这些接口的设计思想和使用方式符合 Spring 后置处理器的特性和用途。我们暂时将这些常用的直接理解为Spring后置处理器。

二、Spring后置处理器在IOC容器和bean对象生命周期的切入时机分析

Spring 后置处理器在 IOC 容器和 Bean 对象生命周期的不同阶段有不同的切入时机:

(一)IOC 容器生命周期中的切入时机

BeanFactoryPostProcessor 的切入时机是在 IOC 容器实例化 BeanDefinition,并将其加载到容器中之后,但在 Bean 实例化之前。它允许对容器中的 BeanDefinition 进行修改,比如修改属性值、添加额外的 BeanDefinition 等。

  • BeanDefinitionRegistryPostProcessor 是 BeanFactoryPostProcessor 的子接口,它在 BeanFactoryPostProcessor 之后执行,但在 Bean 实例化之前。它允许进一步修改 BeanDefinitionRegistry 中的 BeanDefinition,比如注册新的 BeanDefinition。

(二)Bean 对象生命周期中的切入时机

BeanPostProcessor 的切入时机是在 Bean 实例化后,但在 Bean 的初始化方法(如果有)被调用之前(postProcessBeforeInitialization() 方法被调用)和之后(postProcessAfterInitialization() 方法被调用)。它允许在 Bean 初始化前后执行自定义处理逻辑,比如初始化之前执行一些预处理,初始化之后执行一些后处理逻辑。

  • InstantiationAwareBeanPostProcessor 是 BeanPostProcessor 的子接口,提供了更多的回调方法,如 postProcessBeforeInstantiation()postProcessAfterInstantiation()。它允许在 Bean 实例化之前和之后执行自定义逻辑。
  • DestructionAwareBeanPostProcessor 是 BeanPostProcessor 的子接口,它提供了一个额外的回调方法 postProcessBeforeDestruction(),允许在 Bean 销毁之前执行自定义逻辑。
  • MergeBeanDefinitionPostProcessor:实际上是 Spring 内部使用的后置处理器,用于处理合并父子 BeanDefinition 的逻辑。它主要参与了 BeanDefinition 合并的过程,而不是直接影响 Bean 对象的生命周期。因此,在 Bean 对象的生命周期中并没有直接的切入时机与之相关联。

三、BeanPostProcessor后置器分析

(一)源码分析

BeanPostProcessor 接口源码提取如下:

package org.springframework.beans.factory.config;public interface BeanPostProcessor {Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException;Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException;
}

BeanPostProcessor 接口非常简洁,只定义了两个方法,对于开发人员只需要专注于自定义的逻辑即可,不必关注太多的接口方法。

(二)具体切入时机分析

了解 BeanPostProcessor 接口中的两个方法的具体切入时机:

postProcessBeforeInitialization 方法的切入时机

在 Bean 的初始化方法调用之前被调用。当 Spring 容器完成 Bean 的实例化后,但在 Bean 的初始化方法(如果有)被调用之前,会依次遍历所有注册的 BeanPostProcessor,并调用它们的 postProcessBeforeInitialization() 方法。这个时机可以用于在 Bean 初始化之前执行一些预处理逻辑,比如属性设置、依赖注入、初始化前的校验等。

postProcessAfterInitialization 方法的切入时机

在 Bean 的初始化方法调用之后被调用。当 Spring 容器完成 Bean 的实例化和初始化(包括调用初始化方法)后,会依次遍历所有注册的 BeanPostProcessor,并调用它们的 postProcessAfterInitialization() 方法。这个时机可以用于在 Bean 初始化之后执行一些后处理逻辑,比如初始化后的校验、AOP 代理的创建、与其他 Bean 的关联等。

(三)InstantiationAwareBeanPostProcessor派生分析

InstantiationAwareBeanPostProcessor 接口是 BeanPostProcessor 接口的子接口,用于在 Bean 实例化之前和之后执行自定义逻辑。

package org.springframework.beans.factory.config;public interface InstantiationAwareBeanPostProcessor extends BeanPostProcessor {// 在 Bean 实例化之前调用,允许修改即将实例化的 Bean 类型default Class<?> predictBeanType(Class<?> beanClass, String beanName) throws BeansException {return null;}// 在 Bean 实例化之前调用,允许返回另一个实例化的 Bean 类型default Object getEarlyBeanReference(Object bean, String beanName) throws BeansException {return bean;}// 在 Bean 实例化之后调用,允许对 Bean 属性进行修改default Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {return null;}// 在 Bean 实例化之后调用,允许修改或替换已创建的 Bean 实例default boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {return true;}
}

InstantiationAwareBeanPostProcessor 接口定义了四个方法,其中两个继承两个新增:

方法描述返回值
predictBeanType在 Bean 实例化之前调用,允许修改即将实例化的 Bean 类型预测的 Bean 类型
getEarlyBeanReference在 Bean 实例化之前调用,允许返回另一个实例化的 Bean 类型早期引用的 Bean 实例
postProcessBeforeInstantiation在 Bean 实例化之后调用,允许对 Bean 属性进行修改修改后的 Bean 实例
postProcessAfterInstantiation在 Bean 实例化之后调用,允许修改或替换已创建的 Bean 实例是否继续调用后续的 BeanPostProcessor

(四)DestructionAwareBeanPostProcessor派生分析

是 BeanPostProcessor 接口的子接口,提供了一个额外的回调方法用于在 Bean 销毁之前执行自定义逻辑。

package org.springframework.beans.factory.config;public interface DestructionAwareBeanPostProcessor extends BeanPostProcessor {// 在 Bean 销毁之前调用,允许执行一些清理逻辑void postProcessBeforeDestruction(Object bean, String beanName) throws BeansException;
}

切入时机分析

  • postProcessBeforeDestruction() 方法在 Bean 销毁之前调用。
  • 调用时机是在 Spring 容器销毁 Bean 对象之前,允许执行一些清理操作。
  • 这个方法的调用发生在 Bean 的生命周期的末尾阶段,即 Bean 即将被销毁之前。
  • 我们可以在这个方法中执行一些清理工作,比如释放资源、关闭连接、撤销注册等。

我们可以通过实现这个接口可以确保在 Bean 被销毁时进行一些额外的操作,从而保证系统的稳定性和资源的正确释放等。

(五)MergeBeanDefinitionPostProcessor

MergeBeanDefinitionPostProcessor 并不是 Spring Framework 公开的 API,是 Spring 内部使用的一个工具类,用于处理父子 BeanDefinition 合并的逻辑,通常不会直接暴露给外部使用。

MergeBeanDefinitionPostProcessor 的设计思想是在 BeanDefinition 合并过程中插入自定义的处理逻辑。在 Spring 中,当存在父子 BeanDefinition 时,容器会根据一定的合并规则将它们合并成一个完整的 BeanDefinition。MergeBeanDefinitionPostProcessor 就是为了在这个合并过程中提供扩展点,允许我们对合并后的 BeanDefinition 进行进一步的处理,但本身不能对其进行扩展。

四、BeanFactoryPostProcessor后置器分析

(一)源码展示

BeanFactoryPostProcessor 的切入时机是在 Spring 容器标准初始化之后,但在实例化和配置所有的 BeanDefinition 之后:

package org.springframework.beans.factory.config;import org.springframework.beans.BeansException;public interface BeanFactoryPostProcessor {// 在标准初始化之后修改应用程序上下文的工厂void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;
}

内部定义了一个方法 postProcessBeanFactory(),这个方法在标准初始化之后调用,用于修改应用程序上下文的工厂。在这个方法中,我们可以对 BeanFactory 进行各种自定义处理,比如注册额外的 BeanDefinition、修改已存在的 BeanDefinition、添加属性编辑器等。

分析源码实现:postProcessBeanFactory() 方法接收一个 ConfigurableListableBeanFactory 参数,通过这个参数可以获取到应用程序上下文的 BeanFactory,从而对其进行相应的操作。通常,我们会在这个方法中通过调用 BeanFactory 的各种方法来实现自己的逻辑。

(二)切入时机说明

从一开始的原始图中来看的话:BeanFactoryPostProcessor 的切入时机是在 Spring 容器标准初始化之后,但在实例化和配置所有的 BeanDefinition 之后,我们可以具体展开在回顾一下:

  • Spring 容器启动:当应用程序启动时,Spring 容器会加载并初始化所有的 BeanDefinition。
  • BeanFactory 初始化完成:在 BeanFactory 初始化完成之后,容器会调用所有已注册的 BeanFactoryPostProcessor 的 postProcessBeanFactory() 方法。
  • 修改 BeanFactory:在 postProcessBeanFactory() 方法中可以对 BeanFactory 进行各种自定义的操作。这包括但不限于:注册额外的 BeanDefinition、修改已存在的 BeanDefinition、添加属性编辑器、设置属性值等。
  • Bean 实例化前:其在 Bean 实例化之前被调用的,因此它主要用于对 BeanDefinition 进行修改,而不是对已实例化的 Bean 进行操作。

(三)BeanDefinitionRegistryPostProcessor派生分析

是 BeanFactoryPostProcessor 的子接口。与 BeanFactoryPostProcessor 不同的是,BeanDefinitionRegistryPostProcessor 能够访问到 BeanDefinitionRegistry(Bean 定义注册表),可以动态地注册、修改和删除 BeanDefinition。

package org.springframework.beans.factory.support;import org.springframework.beans.factory.config.BeanFactoryPostProcessor;public interface BeanDefinitionRegistryPostProcessor extends BeanFactoryPostProcessor {// 在标准初始化之后修改应用程序上下文的内部 bean 工厂的注册表void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry);
}

继承自 BeanFactoryPostProcessor 接口,在 postProcessBeanFactory 方法外还新增了一个方法 postProcessBeanDefinitionRegistry,这个方法在标准初始化之后修改应用程序上下文的内部 bean 工厂的注册表。

在这个接口中,postProcessBeanDefinitionRegistry 方法接收一个 BeanDefinitionRegistry 参数,通过这个参数可以访问到应用程序上下文的 BeanDefinitionRegistry,即 Bean 定义注册表。我们可以在这个方法中对注册表进行各种自定义处理,比如注册额外的 BeanDefinition、修改已存在的 BeanDefinition、删除不需要的 BeanDefinition 等。

五、Spring后置处理器对比分析

特性BeanPostProcessorBeanFactoryPostProcessor
作用范围单个 Bean 实例整个容器的 BeanDefinition 集合
接口层次BeanPostProcessor 接口BeanFactoryPostProcessor 接口
方法调用时机Bean 实例化后,初始化前后容器启动过程中,标准初始化之后
处理对象单个 Bean 实例整个容器的 BeanDefinition 集合
主要功能对 Bean 进行增强,如 AOP、日志等对容器进行定制化处理,如注册 BeanDefinition、修改属性等
使用场景需要对单个 Bean 进行增强的场景需要对整个容器进行定制化处理的场景

 源码或官方文章

Java-based Container Configuration :: Spring Framework

Bean Scopes :: Spring Framework

Container Overview :: Spring Framework

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/831408.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

OpenCV(三)—— 车牌筛选

本篇文章要介绍如何对从候选车牌中选出最终进行字符识别的车牌。 无论是通过 Sobel 还是 HSV 计算出的候选车牌都可能不止一个&#xff0c;需要对它们进行评分&#xff0c;选出最终要进行识别的车牌。这个过程中会用到两个理论知识&#xff1a;支持向量机和 HOG 特征。 1、支…

Redis__事务

文章目录 &#x1f60a; 作者&#xff1a;Lion J &#x1f496; 主页&#xff1a; https://blog.csdn.net/weixin_69252724 &#x1f389; 主题&#xff1a;Redis__事务 ⏱️ 创作时间&#xff1a;2024年05月02日 ———————————————— 这里写目录标题 文章目…

SSM+Vue在线OA办公系统

在线办公分三个用户登录&#xff0c;管理员&#xff0c;经理&#xff0c;员工。 SSM架构&#xff0c;maven管理工具&#xff0c;数据库Mysql&#xff0c;系统有文档&#xff0c;可有偿安装调试及讲解&#xff0c;项目保证质量。需要划到 最底 下可以联系到我。 功能如下&am…

蓝桥杯练习系统(算法训练)ALGO-950 逆序数奇偶

资源限制 内存限制&#xff1a;256.0MB C/C时间限制&#xff1a;1.0s Java时间限制&#xff1a;3.0s Python时间限制&#xff1a;5.0s 问题描述 老虎moreD是一个勤于思考的青年&#xff0c;线性代数行列式时&#xff0c;其定义中提到了逆序数这一概念。不过众所周知我们…

nginx--location详细使用和账户认证

在没有使用正则表达式的时候&#xff0c;nginx会先在server中的多个location选取匹配度最高的一个uri&#xff0c;uri是用户请求的字符串&#xff0c;即域名后面的web文件路径&#xff0c;然后使用该location模块中的正则url和字符串串&#xff0c;如果匹配成功就结束搜索&…

C语言----贪吃蛇(补充)

各位看官好&#xff0c;我想大家应该已经看过鄙人的上一篇博客贪吃蛇了吧。鄙人在上一篇博客中只是着重的写了贪吃蛇的实现代码&#xff0c;但是前期的一些知识还没有具体的介绍&#xff0c;比如确认光标位置&#xff0c;句柄等。那么我这一篇博客就来补充上一篇博客所留下来的…

神经网络中的优化方法

一、引入 在传统的梯度下降优化算法中&#xff0c;如果碰到平缓区域&#xff0c;梯度值较小&#xff0c;参数优化变慢 &#xff0c;遇到鞍点&#xff08;是指在某些方向上梯度为零而在其他方向上梯度非零的点。&#xff09;&#xff0c;梯度为 0&#xff0c;参数无法优化&…

数据结构-AVL树

目录 什么是 AVL 树 ASL 度量查找效率 结构体定义 平衡调整 调整类型 左旋和右旋 右旋 左旋 左、右平衡调整 左平衡调整 右平衡调整 插入数据 模拟建立 AVL 树 什么是 AVL 树 二叉排序树的形状取决于数据集&#xff0c;当二叉树的高度越小、结构越合理&#xff0c…

thinkphp家政上门预约服务小程序家政保洁师傅上门服务小程序上门服务在线派单安装教程

介绍 thinkphp家政上门预约服务小程序家政保洁师傅上门服务小程序上门服务在线派单安装教程 上门预约服务派单小程序家政小程序同城预约开源代码独立版安装教程 程序完整&#xff0c;经过安装检测&#xff0c;可放心下载安装。 适合本地的一款上门预约服务小程序&#xff0…

计算机网络——初识网络

一、局域网与广域网 1.局域网&#xff08;LAN&#xff09; 局域网&#xff1a;即Local Area Network&#xff0c;简称LAN。Local即标识了局域⽹是本地&#xff0c;局部组建的⼀种私有⽹络。局域⽹内的主机之间能⽅便的进⾏⽹络通信&#xff0c;⼜称为内⽹&#xff1b;局域⽹和…

A4的PDF按A3打印

先用办公软件打开&#xff0c;比如WPS。 选择打印-属性。 纸张选A3&#xff0c;如果是双面打印&#xff0c;选短边装订&#xff0c;然后在版面-页面排版-每张页数&#xff08;N合1&#xff09;选2。 不同打印机的具体配置可能不一样&#xff0c;但大体都是这个套路。

[NSSCTF]prize_p1

前言 之前做了p5 才知道还有p1到p4 遂来做一下 顺便复习一下反序列化 prize_p1 <META http-equiv"Content-Type" content"text/html; charsetutf-8" /><?phphighlight_file(__FILE__);class getflag{function __destruct(){echo getenv(&qu…

The Role of Subgroup Separability in Group-Fair Medical Image Classification

文章目录 The Role of Subgroup Separability in Group-Fair Medical Image Classification摘要方法实验结果 The Role of Subgroup Separability in Group-Fair Medical Image Classification 摘要 研究人员调查了深度分类器在性能上的差异。他们发现&#xff0c;分类器将个…

基于Springboot的民宿管理平台

基于SpringbootVue的民宿管理平台设计与实现 开发语言&#xff1a;Java数据库&#xff1a;MySQL技术&#xff1a;SpringbootMybatis工具&#xff1a;IDEA、Maven、Navicat 系统展示 用户登录 首页 民宿信息 后台登录 后台首页 用户管理 商家管理 民宿信息管理 房间类型管理 …

【正版系统】知识付费系统搭建,系统模板开发完善功能强大,支持快速部署上线

在数字化时代&#xff0c;知识付费已成为一种趋势&#xff0c;为内容创作者和求知者搭建了一个高效的交流平台。今天&#xff0c;我要为大家介绍一款功能强大的知识付费系统。 知识付费系统模板是我们一款经过精心开发、完善的系统&#xff0c;旨在为用户提供一站式的知识付费…

【Docker】如何注册Hub账号并上传镜像到Hub仓库

一、创建Hub账户 浏览器访问&#xff1a;hub.docker.com 点击【Sign up】注册账号 输入【邮箱】【用户名】【密码】 ps&#xff1a;用户名要有字母数字&#xff1b;订阅不用勾选 点击【Sign up】注册即可 点击【Sign in】登录账号 输入【邮箱】【密码】 点击【Continue】登录 二…

Unreal 编辑器工具 批量重命名资源

右键 - Editor Utilities - Editor Utility Blueprint&#xff0c;基类选择 Asset Action Utility 在类默认值内&#xff0c;可以添加筛选器&#xff0c;筛选指定的类型 然后新建一个函数&#xff0c;加上4个输入&#xff1a;ReplaceFrom&#xff0c;ReplaceTo&#xff0c;Add…

大数据学习笔记14-Hive基础2

一、数据字段类型 数据类型 &#xff1a;LanguageManual Types - Apache Hive - Apache Software Foundation 基本数据类型 数值相关类型 整数 tinyint smallint int bigint 小数 float double decimal 精度最高 日期类型 date 日期 timestamps 日期时间 字符串类型 s…

nginx--自定义日志跳转长连接文件缓存状态页

自定义日志服务 [rootlocalhost ~]# cat /apps/nginx/conf/conf.d/pc.conf server {listen 80;server_name www.fxq.com;error_log /data/nginx/logs/fxq-error.log info;access_log /data/nginx/logs/fxq-access.log main;location / {root /data/nginx/html/pc;index index…

使用STM32F103C8T6与蓝牙模块HC-05连接实现手机蓝牙控制LED灯

导言: 在现代智能家居系统中,远程控制设备变得越来越普遍和重要。本文将介绍如何利用STM32F103C8T6单片机和蓝牙模块HC-05实现远程控制LED灯的功能。通过这个简单的项目,可以学会如何将嵌入式系统与蓝牙通信技术相结合,实现远程控制的应用。 目录 导言: 准备工作: 硬…