Spring 中 BeanFactoryPostProcessor 的作用和示例
一、概览
1. 核心定位
BeanFactoryPostProcessor
是 Spring 容器级别的扩展接口,在 Bean 实例化之前,对 Bean 的配置元数据(即 BeanDefinition
)进行动态修改或扩展。其核心功能围绕以下两点:
- 修改现有 Bean 的定义(如属性值、作用域、初始化方法等)。
- 添加新的 Bean 定义(需通过子接口
BeanDefinitionRegistryPostProcessor
)。
2. 核心功能详解
功能 | 场景与示例 |
---|---|
动态调整 Bean 配置 | 修改属性值(如占位符替换)、调整作用域(单例改原型)、覆盖懒加载设置等。 例: PropertySourcesPlaceholderConfigurer 解析 ${} 占位符。 |
注册新 Bean 定义 | 通过子接口 BeanDefinitionRegistryPostProcessor 动态注册新 Bean(如根据条件加载不同实现类)。 |
全局性配置处理 | 批量修改所有 Bean 的公共属性(如统一设置缓存超时时间)。 |
与外部配置集成 | 结合环境变量或远程配置中心,动态覆盖 Bean 的初始配置(如数据库连接参数动态更新)。 |
扩展容器能力 | 注册自定义作用域(如线程级别作用域)、实现模块化配置加载(如插件化架构中的模块注册)。 |
3. 关键特性
-
执行时机:在
BeanDefinition
加载完成之后、Bean 实例化之前(即refresh()
方法中的invokeBeanFactoryPostProcessors
阶段)。 -
作用对象:操作对象是
BeanDefinition
(配置元数据),而非 Bean 实例,避免过早实例化导致性能问题。 -
扩展层级:
- 直接实现:
BeanFactoryPostProcessor
用于修改现有配置。 - 子接口扩展:
BeanDefinitionRegistryPostProcessor
支持新增/删除BeanDefinition
,且执行更早。
- 直接实现:
-
执行顺序:
- 所有
BeanDefinitionRegistryPostProcessor
(优先处理PriorityOrdered
,再Ordered
,最后普通实现)。 - 所有
BeanFactoryPostProcessor
(同上优先级顺序)。
- 所有
二、Spring 内置的 BeanFactoryPostProcessor
1. ConfigurationClassPostProcessor
- 作用:解析
@Configuration
类、@ComponentScan
、@Import
等注解,注册相关BeanDefinition
。 - 实现接口:
BeanDefinitionRegistryPostProcessor
。 - 优先级:
PriorityOrdered
(最高)。 - 源码关键逻辑:
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) {processConfigBeanDefinitions(registry); // 扫描并注册配置类中的 Bean }
2. PropertySourcesPlaceholderConfigurer
- 作用:解析
BeanDefinition
中的占位符(如${jdbc.url}
),替换为Environment
中的实际值。 - 实现接口:
BeanFactoryPostProcessor
。 - 源码关键逻辑:
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {processProperties(beanFactory); // 替换占位符 }
3. EventListenerMethodProcessor
- 作用:扫描
@EventListener
注解,将方法包装为ApplicationListener
并注册到容器。 - 实现接口:
BeanFactoryPostProcessor
。 - 触发时机:
BeanFactoryPostProcessor
阶段注册监听器。
4. CustomScopeConfigurer
- 作用:注册自定义作用域(如
request
、session
)。 - 实现接口:
BeanFactoryPostProcessor
。 - 示例:
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {beanFactory.registerScope("thread", new SimpleThreadScope()); }
三、用户自定义的 BeanFactoryPostProcessor
1. 动态修改 BeanDefinition
public class CustomBeanFactoryPostProcessor implements BeanFactoryPostProcessor {@Overridepublic void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {BeanDefinition beanDef = beanFactory.getBeanDefinition("user");beanDef.getPropertyValues().add("name", "xiaolingting");}
}
2. 注册外部配置客户端
public class ConfigClientPostProcessor implements BeanDefinitionRegistryPostProcessor {@Overridepublic void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) {// 注册远程配置中心客户端registry.registerBeanDefinition("configClient", new RootBeanDefinition(ConfigClient.class));}
}
四、执行流程与源码分析
1. 核心入口方法
在 AbstractApplicationContext#refresh()
中调用:
invokeBeanFactoryPostProcessors(beanFactory);
2. 处理顺序逻辑
-
步骤 1:处理
BeanDefinitionRegistryPostProcessor
实现类:// 获取所有实现类并按优先级排序 String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class); for (String ppName : postProcessorNames) {if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));}// 其他优先级处理... }
-
步骤 2:处理
BeanFactoryPostProcessor
实现类:// 按优先级分组调用 invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory); invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory);
3. 典型场景示例
- 配置类扫描:
ConfigurationClassPostProcessor
在postProcessBeanDefinitionRegistry
阶段扫描@Component
并注册 Bean。 - 占位符替换:
PropertySourcesPlaceholderConfigurer
在postProcessBeanFactory
阶段替换属性值。
五、设计意义与最佳实践
- 扩展性:通过组合模式而非继承,灵活扩展 Spring 容器。
- 性能优化:在 Bean 实例化前修改元数据,避免重复初始化开销。
- 应用场景:
- 动态配置:根据环境变量调整 Bean 属性。
- 插件化架构:运行时注册新组件(如数据库驱动)。
- AOP 前置处理:注册代理相关的
BeanPostProcessor
。
总结:Spring 的 BeanFactoryPostProcessor
是容器初始化的核心扩展点,通过内置和自定义实现,开发者可在不同阶段精确控制 Bean 的元数据和行为,为复杂应用提供强大的底层支持。
附:源码
相关文章:
Spring 中 BeanFactoryPostProcessor 的作用和示例
一、概览 1. 核心定位 BeanFactoryPostProcessor 是 Spring 容器级别的扩展接口,在 Bean 实例化之前,对 Bean 的配置元数据(即 BeanDefinition)进行动态修改或扩展。其核心功能围绕以下两点: 修改现有 Bean 的定义&…...
PDFMathTranslate 安装、使用及接入deepseek
PDFMathTranslate 安装、使用及接入deepseek 介绍安装及使用接入deepseek注意 介绍 PDFMathTranslate 是非常好用的科学 PDF 文档翻译及双语对照工具,可以将论文按照其原本的排版结构执行多种语言翻译,并且可以接入如:谷歌翻译、deepl、deep…...
Docker生存手册:安装到服务一本通
文章目录 一. Docker 容器介绍1.1 什么是Docker容器?1.2 为什么需要Docker容器?1.3 Docker架构1.4 Docker 相关概念1.5 Docker特点 二. Docker 安装2.1 查看Linux内核版本2.2 卸载老版本docker,避免产生影响2.3 升级yum 和配置源2.4 安装Dock…...
JAVA中关于图形化界面的学习(GUI)动作监听,鼠标监听,键盘监听
动作监听: 先创建一个图形化界面,接着创建一个按钮对象,设置按钮的大小。 添加一个addActionListener(); addActionListener() 方法定义在 java.awt.event.ActionListener 接口相关的上下文中,许多支持用户交互产生…...
wepy微信小程序自定义底部弹出框功能,显示与隐藏效果(淡入淡出,滑入滑出)
视图html部分 <view class"salePz"><view class"btnSelPz" tap"pzModelClick">去选择</view><!-- modal --><view class"modal modal-bottom-dialog" hidden"{{hideFlag}}"><view class&q…...
Api架构设计--- HTTP + RESTful
Api架构设计--- HTTP RESTful 什么是RESTfulRESTful 设计原则RESTful 接口类型RESTful 状态码RESTful Uri设计原则Api传参:QueryString 和 UriPath RESTful和HTTP的区别注意事项 什么是RESTful RESTful(Representational State Transfer)是一…...
设计模式-适配器模式
适配器模式是一种结构型设计模式,用于将一个类的接口转换为客户端期望的另一个接口,使得原本不兼容的类可以协同工作。它的核心思想是通过中间层(适配器)解决接口不匹配的问题,类似于电源插头转换器。 核心思想 适配…...
MacBook部署达梦V8手记
背景 使用Java SpringBootDM开发Web应用,框架有License,OSX加载dll失败,安装了Windows 11,只有一个C盘,达梦安装后因为C盘权限问题,创建数据库失败,遂采用Docker容器方式部署。 下载介质 官网在…...
MySQL程序
博主主页: 码农派大星. 数据结构专栏:Java数据结构 数据库专栏:数据库 JavaEE专栏:JavaEE 软件测试专栏:软件测试 关注博主带你了解更多知识 1. mysqld (MySQL服务器) mysqld也被称为MySQL服务器,是⼀个多线程程序,对数据⽬录进⾏访问管理(包含数据库…...
APB-清华联合腾讯等机构推出的分布式长上下文推理框架
APB (Accelerating Distributed Long-Context Inference by Passing Compressed Context Blocks acrossGPUs)是清华大学等机构联合提出的分布式长上下文推理框架。通过稀疏注意力机制和序列并行推理方式,有效解决了大模型处理长文本时的效率瓶颈。APB采用更小的Anch…...
python爬虫笔记(一)
文章目录 html基础标签和下划线无序列表和有序列表表格加边框 html的属性a标签(网站)target属性换行线和水平分割线 图片设置宽高width,height html区块——块元素与行内元素块元素与行内元素块元素举例行内元素举例 表单from标签type属性pla…...
Pycharm接入DeepSeek,提升自动化脚本的写作效率
一.效果展示: 二.实施步骤: 1.DeepSeek官网创建API key: 创建成功后,会生成一个API key: 2. PyCharm工具,打开文件->设置->插件,搜索“Continue”,点击安装 3.安装完成后&…...
spring boot 过滤器简单demo
1. 过滤器(Filter)的概念 过滤器是 Java Web 应用中的一种组件,它可以在请求到达目标资源(如 Controller)之前或响应返回客户端之后,对请求和响应进行统一处理。它的核心作用是对 HTTP 请求和响应进行拦截…...
3.8 Spring Boot监控:Actuator+Prometheus+Grafana可视化
在Spring Boot应用中,通过整合Actuator、Prometheus和Grafana可以构建完整的监控体系,实现指标采集、存储和可视化。以下是具体实现步骤: 一、Spring Boot Actuator 配置 作用:暴露应用健康指标、性能数据等监控端点。 1. 添加依…...
C++中的单例模式及具体应用示例
AI 摘要 本文深入探讨了C中的单例模式及其在机器人自主导航中的应用,特别是如何通过单例模式来管理地图数据。文章详细介绍了单例模式的基本结构、优缺点以及在多线程环境中的应用,强调了其在保证数据一致性和资源管理中的重要性。 接着,文章…...
网络编程——套接字、创建服务器、创建客户端
一、套接字 1.1什么是套接字 套接字文件,原本就是一个和管道文件类似,用来实现进程间通信的一个文件 既然有了管道文件,当时为什么还要开发套接字文件,去实现进程的通信 因为管道文件是半双工模式的 套接字文件是全双工模式的…...
【设计模式】3W 学习法深入剖析创建型模式:原理、实战与开源框架应用(含 Java 代码)
3W 学习法总结创建型模式(附 Java 代码实战及开源框架应用) 创建型模式主要关注 对象的创建,旨在提高代码的可复用性、可扩展性和灵活性。本文采用 3W 学习法(What、Why、How),深入分析 五大创建型模式&am…...
软考系统架构师考试目录(2023新版)
论文 2023下半年 开发:论面向对象设计的应用与实现大数据:论多数据源集成的应用与实现测试:论软件可靠性评价的设计与实现运维:论边云协同的设计与实现 2024上半年 大数据:Lambda架构,分层批处理层、加…...
Apifox Helper 自动生成API接口文档
在我们开发过程中我们在编写请求地址和编写请求参数的时候特别花费时间耗费了我们很多时间,作为一个程序员,更应该把精力时间集中在开发上, Apifox Helper 是 Apifox 团队针对 IntelliJ IDEA 环境所推出的插件,可以在 IDEA 环境中…...
MySQL开发陷阱与最佳实践:第1章:MySQL开发基础概述-1.1 MySQL简介与应用场景
👉 点击关注不迷路 👉 点击关注不迷路 👉 点击关注不迷路 文章大纲 MySQL开发陷阱与最佳实践:第1章:MySQL开发基础概述-1.1 MySQL简介与应用场景1.1.1 MySQL的发展历程与市场地位1.1.2 MySQL的核心特性与技术优势1.1.2…...
电鱼智能EFISH-RK3576-SBC工控板已适配Android 14系统
EFISH-RK3576-SBC工控板此前已提供了Linux 6.1.57系统,为了满足更多客户的需求,电鱼智能近日又为其成功适配了Android 14系统——硬件性能卓越的核心板与Android 14的深度组合,将为用户带来更加流畅、开放、智能的使用体验。 一、高性能处理器…...
C++ 语法之函数和函数指针
在上一章中 C 语法之 指针的一些应用说明-CSDN博客 我们了解了指针变量,int *p;取变量a的地址这些。 那么函数同样也有个地址,直接输出函数名就可以得到地址,如下: #include<iostream> using namespace std; void fun() …...
LabVIEW生成EXE文件错误提示
在LabVIEW生成EXE时弹出 “The build is missing one or more source files or items the source files reference on disk”,表明项目中引用的某些文件(如VI、子模块、依赖库或配置文件)未被正确包含或路径丢失。以下是具体原因及解决方案&a…...
HTML,CSS,JavaScript
HTML:负责网页的结构(页面元素和内容)。 CSS:负责网页的表现(页面元素的外观、位置等页面样式,如:颜色、大小等)。 Javascript:负责网页的行为(交互效果)。 MDN前端开发文档(MDN Web Docs) HTML HTML(HyperText Markup Language):超文本标记语言超文本:超越了文本的…...
SpringCloud 学习笔记2(Nacos)
Nacos Nacos 下载 Nacos Server 下载 | Nacos 官网 下载、解压、打开文件: 更改 Nacos 的启动方式 Nacos 的启动模式默认是集群模式。在学习时需要把他改为单机模式。 把 cluster 改为 standalone,记得保存! 启动startup.cmd Ubuntu 启动…...
Qt5.15.2实现Qt for WebAssembly与示例
目录 1.什么是Qt for WebAssembly? 1.1 什么是 WebAssembly? 1.2 WebAssembly 的优势 1.3 什么是 Qt for WebAssembly? 1.4 Qt for WebAssembly 的特点 1.5 编译过程 1.6 运行时环境 注意!!!注意&am…...
荣耀手机怎么录制屏幕?屏幕录制后为视频加水印更有“安全感”
在数字时代,屏幕录制已经成为记录和分享信息的重要方式之一。无论是记录游戏的高光时刻,还是制作教学视频,亦或是保存重要的线上会议内容,屏幕录制都能轻松搞定。 荣耀手机作为一款功能强大的设备,自然也提供了便捷的…...
3DXML 与 SOLIDWORKS 格式转换:技术协同及迪威模型方案
一、引言 在产品设计的前沿领域,3DXML 与 SOLIDWORKS 作为主流格式,虽各有所长,但因格式差异,常成为数据流通与协作的阻碍。对于技术人员和学生党而言,掌握二者间的转换技术,不仅能提升设计效率࿰…...
CH347使用笔记:CH347结合STM32CubeIDE实现单片机下载与调试
目录 基于 STM32CubeIDE的 CH347 JTAG/SWD调试器使用说明1. CH347驱动安装与配置2. STM32CubeIDE调试器配置2.1 打开相关工程后,进行以下操作2.2 openocd.exe替换2.3 脚本添加2.4 更改调试器选择 3. 下载程序4. 使用过程中可能遇到的问题4.1 CH347未插入4.2 Openocd…...
JS—基本数据类型和引用数据类型:1分钟掌握两者的区别
个人博客:haichenyi.com。感谢关注 一. 目录 一–目录二–分类三–核心区别四–实际场景中的问题五–总结对比 二. 分类 前面说过这么判断数据类型,今天来说说基本数据类型和引用数据类型的区别。 基本数据类型引用数据类型StringObjectNumberFunct…...
使用 CryptoJS 实现 AES 解密:动态数据解密示例
在现代加密应用中,AES(高级加密标准)是一种广泛使用的对称加密算法。它的安全性高、效率好,适合用于各种加密任务。今天,我们将通过一个实际的示例,展示如何使用 CryptoJS 实现 AES 解密,解密动态数据。CryptoJS 是一个基于 JavaScript 的加密库,它支持 AES、DES 等多种…...
[设计模式与源码]1_Spring三级缓存中的单例模式
欢迎来到啾啾的博客🐱,一个致力于构建完善的Java程序员知识体系的博客📚,记录学习的点滴,分享工作的思考、实用的技巧,偶尔分享一些杂谈💬。 欢迎评论交流,感谢您的阅读😄…...
使用React和google gemini api 打造一个google gemini应用
实现一个简单的聊天应用,用户可以通过输入问题或点击“Surprise me”按钮获取随机问题,并从后端API获取回答。 import { useState } from "react"; function App() {const [ value, setValue] useState(""); // 存储用户输入的问题…...
为什么Django能有效防御CSRF攻击?
在当今这个互联网高度发达的时代,Web安全问题层出不穷,其中跨站请求伪造(CSRF,Cross-Site Request Forgery)就是一个比较常见的威胁。攻击者利用用户的身份信息,发送恶意请求,改变用户的属性或执…...
Oracle常见系统函数
一、字符类函数 1,ASCII(c)和CHR(i)字符串和ascii码互转换 SQL> select ascii(Z) ,ascii(H),ascii( A) from dual;ASCII(Z) ASCII(H) ASCII(A) ---------- ---------- ----------90 72 32SQL> select chr(90),chr(72),chr(65) from dual;C…...
【Visio使用教程】
Visio使用教程 1. Visio 的基本介绍1.1 Visio 是什么?核心特点: 1.2 主要功能与应用场景典型用途:行业应用: 1.3 版本与兼容性1.4 Visio下载1.5 安装 2. Visio 的界面与基础操作2.1 界面布局详解2.2 创建新文档与模板选择2.3 形状…...
蓝桥杯 修剪灌木
问题描述 爱丽丝要完成一项修剪灌木的工作。 有 N 棵灌木整齐的从左到右排成一排。爱丽丝在每天傍晩会修剪一棵灌 木, 让灌木的高度变为 0 厘米。爱丽丝修剪灌木的顺序是从最左侧的灌木开始, 每天向右修剪一棵灌木。当修剪了最右侧的灌木后, 她会调转方向, 下一天开 始向左修…...
HTML中滚动加载的实现
设置div的overflow属性,可以使得该div具有滚动效果,下面以div中包含的是table来举例。 当table的元素较多,以至于超出div的显示范围的话,观察下该div元素的以下3个属性: clientHeight是div的显示高度,scrol…...
bbbbb
import java.util.ArrayList; import java.util.List; public class KthPermutation { public static String getPermutation(int n, int k) { // 计算阶乘 int[] factorial new int[n]; factorial[0] 1; for (int i 1; i < n; i) …...
Linux文件
1.Open函数 高频使用的Linux系统调用:open write read close Linux自带的工具:man手册: man 1是普通的shell命令,比如ls man 2是系统调用函数,比如open,write说明 在Linux系统库的定义: int o…...
kafka指北
为自己总结一下kafka指北,会持续更新。创作不易,转载请注明出处。 目录 集群controller选举过程broker启动流程 主题创建副本分布ISRleader副本选举机制LEO 生产数据流程同步发送和异步发送 分区策略ack应答生产者发送消息的幂等性跨分区幂等性问题&…...
Linux安装部署Elasticsearch8 全过程记录
一、安装 Elasticsearch8 1、下载 访问 Elasticsearch 官方网站(Download Elasticsearch | Elastic)。 在下载页面找到 Elasticsearch 8 的 Linux 版本(.tar.gz 格式)下载链接,点击下载。 下载Elasticsearch8&…...
ESP32(3)UDP通信
对于 lwIP 的 Socket 的使用方式,它与文件操作非常相似。在文件操作中,我们首先打开文件,然后进行读/写操作,最后关闭文件。在TCP/IP网络通信中,也存在着相同的操作流程,但所使用的接口不再是文件描述符或 …...
汽车机械钥匙升级一键启动的优点
汽车机械钥匙升级一键启动的优点主要包括: 便捷性:一键启动功能的引入极大地提升了用车便捷性。车主无需翻找钥匙,只需在车辆感应范围内轻触启动键,即可轻松发动汽车。 安全性:移动管家专车专用一键启动系统配备了防…...
【matlab例程】三维下的TDOA定位和EKF轨迹滤波例程,TDOA的锚点数量可自定义(订阅专栏后可获得完整代码)
本文所述的MATLAB例程实现了TDOA定位和扩展卡尔曼滤波(EKF)来提高位置估计的准确性,并通过可视化结果进行分析。 文章目录 运行结果MATLAB代码程序讲解关键步骤和功能步骤解释注意事项总结运行结果 三维轨迹: 三维误差曲线: RMSE曲线: 命令行输出内容:...
个人blog系统 前后端分离 前端js后端go
系统设计: 1.使用语言:前端使用vue,并使用axios向后端发送数据。后端使用的是go的gin框架,并使用grom连接数据库实现数据存储读取。 2.设计结构: 最终展示:仅展示添加模块,其他模块基本相似 前…...
OSG简介
OSG OpenSceneGraph (简称 OSG) 是一个开源的高性能3D图形库。 作用 它为开发者提供了一个强大的API,处理和渲染复杂的3D图形。 特点 OSG基于OpenGL构建,提供了对现代图形技术的支持,如着色器、纹理映射、光照模型等高级特性。 跨平台支…...
社区版Uos20.9从源码编译QT5.15.2
主要是在这个文章上学的究极保姆式教你如何在Ubuntu上源码安装Qt5.15.2_ubuntu安装qt5.15.2-CSDN博客 但原文上在环境变量的配置上真用在 uso上好像不行,要加一些引号和$号。原文的测试编译代码也有些问题,include上少了类。略作修改,在UOS社…...
AI学习第二天--大模型压缩(量化、剪枝、蒸馏、低秩分解)
目录 1. 量化:压缩大象的“脂肪” 比喻 技术逻辑 2. 剪枝:修剪大象的“无效毛发” 比喻 技术逻辑 3. 知识蒸馏:让大象“师从巨象” 比喻 技术逻辑 4. 低秩分解:把大象“折叠成纸偶” 比喻 技术逻辑 5. 推理优化&#…...
C++ —— 线程同步(互斥锁)
C —— 线程同步(互斥锁) 线程同步互斥锁(互斥量)测试代码mutex互斥锁 线程同步 线程同步:多线程协同工作,协商如何使用共享资源。 C11线程同步包含三部分内容: 互斥锁(互斥量&…...