Post-Processing PropertySource instance详解 和 BeanFactoryPostProcessor详解

PropertySourcesBeanFactoryPostProcessor详解

在这里插入图片描述


1. 核心概念

BeanFactoryPostProcessor 是 Spring 框架中用于在 BeanFactory 初始化阶段Environment 中的 PropertySource 进行后处理的接口。它允许开发者在 Bean 创建之前 对属性源进行动态修改,例如添加、删除或转换属性。


2. 核心流程与类关系
2.1 核心接口与实现
  • 接口定义

    public interface PropertySourcesBeanFactoryPostProcessor {void postProcessPropertySources(ConfigurableListableBeanFactory beanFactory, MutablePropertySources propertySources);
    }
    
    • 参数
      • ConfigurableListableBeanFactory:Spring 的 BeanFactory 实例。
      • MutablePropertySources:可修改的属性源集合(包含所有已加载的 PropertySource)。
  • 作用
    在 BeanFactory 初始化过程中,提供对 PropertySource 的直接修改能力,例如:

    • 动态添加自定义属性源(如从数据库读取配置)。
    • 过滤敏感属性(如密码)。
    • 调整属性源的优先级。

3. 典型使用场景
3.1 动态添加 PropertySource
// 示例:从数据库加载配置并添加到 PropertySources
public class DatabasePropertySourcePostProcessor implements PropertySourcesBeanFactoryPostProcessor {@Overridepublic void postProcessPropertySources(ConfigurableListableBeanFactory beanFactory, MutablePropertySources propertySources) {// 1. 从数据库获取配置Map<String, Object> dbProps = loadConfigFromDatabase();// 2. 创建自定义 PropertySourcePropertySource<?> dbPropertySource = new MapPropertySource("databaseConfig", dbProps);// 3. 将其添加到最高优先级(覆盖现有配置)propertySources.addFirst(dbPropertySource);}
}
3.2 过滤敏感属性
public class SensitivePropertyFilter implements PropertySourcesBeanFactoryPostProcessor {@Overridepublic void postProcessPropertySources(ConfigurableListableBeanFactory beanFactory, MutablePropertySources propertySources) {// 遍历所有 PropertySource 并过滤敏感键List<PropertySource<?>> filteredSources = new ArrayList<>();for (PropertySource<?> source : propertySources) {if (source instanceof EnumerablePropertySource) {Map<String, Object> filteredProps = new HashMap<>();for (String key : ((EnumerablePropertySource<?>) source).getPropertyNames()) {if (!key.contains("password")) {filteredProps.put(key, source.getProperty(key));}}PropertySource<?> filteredSource = new MapPropertySource(source.getName(), filteredProps);filteredSources.add(filteredSource);}}// 替换原有的 PropertySourcespropertySources.clear();propertySources.addAll(filteredSources);}
}
3.3 调整属性源优先级
public class CustomPropertyOrderPostProcessor implements PropertySourcesBeanFactoryPostProcessor {@Overridepublic void postProcessPropertySources(ConfigurableListableBeanFactory beanFactory, MutablePropertySources propertySources) {// 将某个 PropertySource 移动到最高优先级PropertySource<?> sourceToMove = propertySources.get("customConfig");if (sourceToMove != null) {propertySources.remove("customConfig");propertySources.addFirst(sourceToMove);}}
}

4. 实现步骤
4.1 定义处理器
public class CustomPropertyProcessor implements PropertySourcesBeanFactoryPostProcessor {@Overridepublic void postProcessPropertySources(ConfigurableListableBeanFactory beanFactory, MutablePropertySources propertySources) {// 在此处实现属性源的修改逻辑}
}
4.2 注册处理器

通过 @Bean 注册到 Spring 容器:

@Configuration
public class AppConfig {@Beanpublic PropertySourcesBeanFactoryPostProcessor customProcessor() {return new CustomPropertyProcessor();}
}
4.3 集成到 Spring Boot

在 Spring Boot 中,可以通过 EnvironmentPostProcessor 在启动时注入:

public class CustomEnvironmentPostProcessor implements EnvironmentPostProcessor {@Overridepublic void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) {// 在此处注册 PropertySourcesBeanFactoryPostProcessor}
}

5. 关键流程与方法
5.1 属性源处理流程
Spring Boot 启动 →加载所有 PropertySource(如 application.properties、环境变量等) →调用 PropertySourcesBeanFactoryPostProcessor.postProcessPropertySources() →修改后的 PropertySources 用于后续 Bean 的属性注入。
5.2 核心方法详解
方法说明
postProcessPropertySources()核心方法,接收 BeanFactoryMutablePropertySources,进行属性源修改。
propertySources.addFirst(source)将属性源添加到最高优先级(覆盖现有配置)。
propertySources.remove(name)移除指定名称的属性源。
propertySources.get(name)根据名称获取属性源。

6. 典型应用场景总结
场景解决方案示例代码片段
动态配置注入从数据库/远程服务加载配置并添加为 PropertySource。propertySources.addFirst(new MapPropertySource("dbConfig", dbProps));
敏感信息过滤移除或修改包含敏感信息的属性键(如密码)。if (!key.contains("password")) { ... }
优先级调整将自定义配置的优先级设为最高,覆盖默认配置。propertySources.addFirst(existingSource);
属性值转换将字符串属性转换为复杂类型(如 ListMap)。Map<String, Object> convertedProps = ...

7. 注意事项
  1. 执行时机:在 BeanFactory 初始化阶段执行,早于 @PostConstruct 和 Bean 初始化。
  2. 优先级控制:通过 addFirst()addLast()insertBefore()/insertAfter() 精确控制属性源顺序。
  3. 副作用风险:避免在处理器中执行耗时操作,可能影响应用启动速度。
  4. Spring Boot 集成:需确保处理器在 Environment 初始化后被正确调用。

8. 总结表格
功能实现方式适用场景
动态配置注入通过 addFirst() 添加自定义 PropertySource。需要从外部源(如数据库)加载配置时。
属性过滤遍历 PropertySources 并移除敏感键。隐藏敏感配置(如数据库密码、API密钥)。
优先级调整使用 addFirst()remove() 调整属性源顺序。需要高优先级配置覆盖默认值(如测试环境覆盖生产配置)。
属性值转换在处理器中修改属性值类型(如字符串转 List)。需要动态解析复杂类型配置时。

通过 PropertySourcesBeanFactoryPostProcessor,可以灵活控制属性源的加载和修改逻辑,满足复杂配置需求。

延伸阅读

Post-Processing PropertySource instance详解


1. 核心概念

PropertySource 是 Spring 框架中用于管理配置属性的抽象类,负责从不同来源(如 application.properties、环境变量、系统属性等)加载属性值。
Post-Processing 是指在 PropertySource 被创建或注册到 Environment 后,对其内容进行进一步的处理或修改。


2. 核心流程与类关系
2.1 核心类与接口
类/接口作用
PropertySource属性源的抽象基类,封装属性键值对(如 server.port=8080)。
EnvironmentSpring 的环境对象,管理所有 PropertySource 的优先级和合并逻辑。
PropertySources存储 PropertySource 集合的容器,按优先级排序。
PropertySourceProcessorPropertySource 进行后处理的接口(如过滤、转换属性)。
PropertySourcesPropertyResolver根据优先级从多个 PropertySource 中解析属性值的工具类。
2.2 核心流程
  1. 属性源加载:Spring Boot 启动时,从 application.properties、YAML 文件、环境变量等加载属性,生成多个 PropertySource 实例。
  2. 属性源注册:将所有 PropertySource 注册到 EnvironmentPropertySources 容器中。
  3. 后处理阶段:对已注册的 PropertySource 进行统一处理(如过滤敏感属性、替换占位符、合并配置等)。

3. 典型 Post-Processing 场景
3.1 属性过滤
  • 场景:隐藏敏感属性(如密码、API密钥)。
  • 实现方式
    // 自定义 PropertySourceProcessor
    public class SensitivePropertyFilter implements PropertySourceProcessor {@Overridepublic PropertySource<?> processPropertySource(PropertySource<?> source) {if (source.getName().equals("someConfig")) {Map<String, Object> filteredProps = new HashMap<>();((MapPropertySource) source).forEach((key, value) -> {if (!key.contains("password")) {filteredProps.put(key, value);}});return new MapPropertySource(source.getName(), filteredProps);}return source;}
    }
    
3.2 属性值转换
  • 场景:将字符串属性转换为其他类型(如 ListMap)。
  • 实现方式
    public class TypeConverterProcessor implements PropertySourceProcessor {@Overridepublic PropertySource<?> processPropertySource(PropertySource<?> source) {Map<String, Object> convertedProps = new HashMap<>();((MapPropertySource) source).forEach((key, value) -> {if (key.endsWith(".asList")) {convertedProps.put(key, Arrays.asList(value.toString().split(",")));} else {convertedProps.put(key, value);}});return new MapPropertySource(source.getName(), convertedProps);}
    }
    
3.3 属性覆盖与合并
  • 场景:根据优先级合并多个属性源(如 application.properties 覆盖默认配置)。
  • 实现方式
    // Spring 的默认合并逻辑由 PropertySourcesPropertyResolver 处理
    Environment env = ...;
    String value = env.getProperty("key"); // 自动按优先级合并
    

4. 自定义 Post-Processing 的实现步骤
4.1 实现 PropertySourceProcessor
public class CustomPropertyProcessor implements PropertySourceProcessor {@Overridepublic PropertySource<?> processPropertySource(PropertySource<?> source) {// 在此处修改或过滤 PropertySourcereturn source; // 返回修改后的 PropertySource}
}
4.2 注册处理器
@Configuration
public class PropertyConfig {@Beanpublic PropertySourceProcessor customProcessor() {return new CustomPropertyProcessor();}
}
4.3 集成到 Spring Boot

通过 EnvironmentPostProcessor 在启动时注入处理器:

public class CustomEnvironmentPostProcessor implements EnvironmentPostProcessor {@Overridepublic void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) {environment.getPropertySources().addFirst(new CustomPropertySourceProcessor().processPropertySource(...));}
}

5. 关键方法与流程
5.1 属性解析流程
Environment.getProperty(key) →PropertySourcesPropertyResolver →遍历 PropertySources(按优先级) →调用 PropertySource.getProperty(key) →返回第一个非空值
5.2 核心方法详解
方法作用
PropertySource.getProperty(key)根据键直接从当前属性源获取值。
PropertySources.getFirst(name)根据名称获取第一个匹配的属性源。
PropertySources.addFirst(source)将属性源添加到优先级最高位置(覆盖现有配置)。

6. 典型应用场景
场景解决方案
敏感属性过滤实现 PropertySourceProcessor 过滤敏感键(如 password)。
动态属性注入EnvironmentPostProcessor 中动态添加属性源(如从数据库读取配置)。
属性值类型转换使用 PropertySourceProcessor 将字符串转换为复杂类型(如 ListMap)。
多环境配置合并按优先级加载 application-{profile}.properties 并合并到 Environment。

7. 总结表格
功能实现方式适用场景
属性过滤实现 PropertySourceProcessor 过滤敏感键。隐藏敏感配置(如数据库密码)。
属性转换在处理器中修改属性值类型(如字符串转 List)。需要动态解析复杂类型配置时。
属性覆盖通过 PropertySources.addFirst() 调整属性源优先级。需要高优先级配置覆盖默认值(如测试环境覆盖生产配置)。
动态属性注入EnvironmentPostProcessor 中注册新 PropertySource。配置需从外部源(如数据库、API)动态加载时。

8. 注意事项
  1. 优先级控制:属性源的加载顺序决定了覆盖规则,需通过 PropertySources.addFirst()addLast() 明确优先级。
  2. 性能影响:复杂的后处理逻辑可能增加启动时间,需避免在高频路径中执行。
  3. Spring Boot 集成:通过 @ConfigurationEnvironmentPostProcessor 灵活扩展。

通过以上方法,可以灵活控制属性源的后处理逻辑,满足复杂配置需求。

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

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

相关文章

[C]基础13.深入理解指针(5)

博客主页&#xff1a;向不悔本篇专栏&#xff1a;[C]您的支持&#xff0c;是我的创作动力。 文章目录 0、总结1、sizeof和strlen的对比1.1 sizeof1.2 strlen1.3 sizeof和strlen的对比 2、数组和指针笔试题解析2.1 一维数组2.2 字符数组2.2.1 代码12.2.2 代码22.2.3 代码32.2.4 …

赛灵思 XCKU115-2FLVB2104I Xilinx Kintex UltraScale FPGA

XCKU115-2FLVB2104I 是 AMD Xilinx Kintex UltraScale FPGA&#xff0c;基于 20 nm 先进工艺&#xff0c;提供高达 1 451 100 个逻辑单元&#xff08;Logic Cells&#xff09;&#xff0c;77 721 600 bit 的片上 RAM 资源&#xff0c;以及 5 520 个 DSP 切片&#xff08;DSP48E…

CAPL编程_03

1_文件操作的相关函数&#xff1a; 读文本文件内容 读取文本文件操作的三部曲 1&#xff09;打开文件 —— openFileRead ( ) 2&#xff09;逐行读取 —— fileGetString ( ) 、fileGetStringSZ ( ) 3&#xff09;关闭文件 —— fileClose ( ) char content[100];…

2025年江西建筑安全员A证适合报考人群

江西建筑安全员A证适合报考人群 江西省建筑安全员A证&#xff08;建筑施工企业主要负责人安全生产考核合格证书&#xff09;主要面向建筑行业管理人员&#xff0c;适合以下人员报考&#xff1a; 1. 企业主要负责人 法人代表、总经理、分管安全副总&#xff1a;依法需持A证&a…

Docker安装(Ubuntu22版)

前言 你是否还在为Linux上配置Docker而感到烦恼&#xff1f; 你是否还在为docker search&#xff0c;docker pull连接不上&#xff0c;而感到沮丧&#xff1f; 本文将解决以上你的所有烦恼&#xff01;快速安装好docker&#xff01; Docker安装 首先&#xff0c;我们得先卸载…

Ubuntu18.04配置C++环境和Qt环境

Ubuntu18.04配置C环境和Qt环境 1、前言3.2 安装其他库3.3 查看有没有安装成功3.4测试C环境 4、配置Qt环境4.1 安装相关的库4.2 测试 5、总结 1、前言 记录一下Ubuntu18.04配置C环境和Qt环境的过程&#xff0c;方便自己日后回顾&#xff0c;也可以给有需要的人提供帮助。 # 2…

ACWing——算法基础课

置顶思考&#xff1a; 算法的本质是什么样的思想&#xff1f; 这种思想可以解决哪类问题&#xff1f; 有没有其他的解决思路&#xff1f; 关注数值范围&#xff0c;思考可不可以针对性解决问题&#xff1f; 目录 https://leetcode.cn/circle/discuss/RvFUtj/ 滑动窗口与双指针…

私钥连接服务器(已经有服务器私钥

前言&#xff1a;假设我们已经有了服务器的私钥&#xff0c;我们怎么配置呢&#xff1f; 下面我会从vsc的配置角度来写 ✅ 步骤一&#xff1a;准备工作 安装 VS Code&#xff08;如果还没装&#xff09; &#x1f449; https://code.visualstudio.com/ 安装插件&#xff1a;Re…

Redis LFU 策略参数配置指南

一、基础配置步骤‌ 设置内存上限‌ 在 redis.conf 配置文件中添加以下指令&#xff0c;限制 Redis 最大内存使用量&#xff08;例如设置为 4GB&#xff09;&#xff1a; maxmemory 4gb选择 LFU 淘汰策略‌ 根据键的作用域选择策略&#xff1a; # 所有键参与淘汰 maxmemory-…

嵌入式 C 语言面试核心知识点全面解析:基础语法、运算符与实战技巧

在嵌入式面试中&#xff0c;C 语言基础是重中之重。本文针对经典面试题进行详细解析&#xff0c;帮助新手系统掌握知识点&#xff0c;提升面试应对能力。 一、数据结构逻辑分类 题目 在数据结构中&#xff0c;从逻辑上可以把数据结构分为&#xff08; &#xff09;。 A、动态…

11.AOP开发

十一、AOP开发 1、Spring Boot实现 AOP 11.1.1、SpringBootAop简介 Spring Boot的AOP编程和Spring框架中AOP编程的唯一区别是&#xff1a;引入依赖的方式不同,其他内容完全一样 Spring Boot中AOP编程需要引入aop启动器&#xff1a; <!--aop启动器--> <dependency…

【网络入侵检测】基于源码分析Suricata的PCAP模式

【作者主页】只道当时是寻常 【专栏介绍】Suricata入侵检测。专注网络、主机安全,欢迎关注与评论。 1. 概要 👋 本文聚焦于 Suricata 7.0.10 版本源码,深入剖析其 PCAP 模式的实现原理。通过系统性拆解初始化阶段的配置流程、PCAP 数据包接收线程的创建与运行机制,以及数据…

.NET 10 中的新增功能

.NET 运行时 .NET 10 运行时引入了新功能和性能改进。 关键更新包括&#xff1a; 数组接口方法反虚拟化&#xff1a;JIT 现在可以取消虚拟化和内联数组接口方法&#xff0c;从而提高数组枚举的性能。数组枚举去抽象化&#xff1a;改进功能以通过枚举器减少数组迭代的抽象开销…

盲注命令执行(Blind Command Execution)

一、核心原理 1. 无回显命令执行的本质 盲命令执行&#xff08;Blind Command Execution&#xff09;是一种攻击形式&#xff0c;攻击者通过注入系统命令到Web应用或后端系统中&#xff0c;但无法直接获取命令执行结果。盲命令执行的本质在于攻击者无法直接看到执行结果&#x…

Linux多线程技术

什么是线程 在一个程序里的多执行路线就是线程。线程是进程中的最小执行单元&#xff0c;可理解为 “进程内的一条执行流水线”。 进程和线程的区别 进程是资源分配的基本单位&#xff0c;线程是CPU调度的基本单位。 fork创建出一个新的进程&#xff0c;会创建出一个新的拷贝&…

计算机组成原理实验(1) 算术逻辑运算单元实验

实验一 算术逻辑运算单元实验 一、实验目的 1、掌握简单运算器的数据传输方式 2、掌握74LS181的功能和应用 二、实验内容 1、不带进位位逻辑或运算实验 2、不带进位位加法运算实验 3、实验指导书2.15实验思考 三、实验步骤和结果 实验内容一&#xff1a;不带进位…

Android将启动画面实现迁移到 Android 12 及更高版本

如果在 Android 11 或更低版本中实现自定义启动画面&#xff0c;请迁移应用迁移到 SplashScreen API 以获取帮助 确保其在 Android 12 及更高版本中正确显示。 从 Android 12 开始&#xff0c;在所有应用的冷启动和温启动期间&#xff0c;系统都会应用 Android 系统的默认启动…

692. 前K个高频单词(map的练习)

目录 1、题目分析 2.解题思路 3.代码实现 4.总结 1、题目分析 2.解题思路 首先它给出我们一个string&#xff0c;让我们提取出它们中出现次数最多的。利用map将word一个一个存入其中&#xff0c;没有就插入&#xff0c;有了就1&#xff0c;这样我们就得到了key_value&#…

如何创建极狐GitLab 议题?

极狐GitLab 是 GitLab 在中国的发行版&#xff0c;关于中文参考文档和资料有&#xff1a; 极狐GitLab 中文文档极狐GitLab 中文论坛极狐GitLab 官网 创建议题 (BASIC ALL) 创建议题时&#xff0c;系统会提示您输入议题的字段。 如果您知道要分配给议题的值&#xff0c;则可…

day32 学习笔记

文章目录 前言一、霍夫变换二、标准霍夫变换三、统计概率霍夫变换四、霍夫圆变换 前言 通过今天的学习&#xff0c;我掌握了霍夫变换的基本原本原理及其在OpenCV中的应用方法 一、霍夫变换 霍夫变换是图像处理中的常用技术&#xff0c;主要用于检测图像中的直线&#xff0c;圆…