当前位置: 首页 > news >正文

Spring Boot-加载配置文件ConfigDataEnvironmentPostProcessor

org.springframework.boot.context.config.ConfigDataEnvironmentPostProcessor是 Spring Boot 中的一个关键组件,它负责处理配置数据(config data),并将其应用于 Spring 应用上下文中。下面我们详细解读这个类的产生背景、作用和工作原理。

产生背景

在 Spring Boot 中,配置数据是指来自各种外部来源(如 YAML 文件、properties 文件、环境变量、命令行参数等)的配置信息。Spring Boot 提供了一种机制来自动读取这些配置信息,并将它们绑定到应用中的 Bean 上。为了更好地管理和处理这些配置数据,Spring Boot 引入了配置数据功能,其中包括 `ConfigData` 和 `ConfigDataLocation` 等概念。

作用

`ConfigDataEnvironmentPostProcessor` 的主要作用是处理配置数据,并将这些数据合并到应用的环境配置中。具体来说,它执行以下几个关键任务:

1. 加载配置数据:从不同的配置源(如文件系统、类路径、云配置中心等)加载配置数据。
2. 解析配置数据:解析加载的配置数据,并将其转换为 Spring 可以理解的格式。
3. 合并配置数据:将解析后的配置数据合并到 `ConfigurableEnvironment` 中。
4. 处理占位符:解析配置数据中的占位符,并将其替换为实际的值。

工作原理

`ConfigDataEnvironmentPostProcessor` 的工作原理涉及以下几个步骤:

1. 实例化:在 Spring 应用启动时,`ConfigDataEnvironmentPostProcessor` 会作为 `BeanFactoryPostProcessor` 的一部分被实例化。
2. 配置数据定位:通过 `ConfigDataLocationResolver` 来确定配置数据的位置。
3. 加载配置数据:使用 `ConfigDataLoader` 来加载配置数据。
4. 解析配置数据:使用 `ConfigDataParser` 来解析加载的数据。
5. 合并配置数据:将解析后的配置数据合并到 `ConfigurableEnvironment` 中。
6. 处理占位符:在合并过程中处理配置数据中的占位符。

源码流程:

这个类有个成员变量postProcessorsFactory,是个函数,函数签名是接受ClassLoader类型参数,返回EnvironmentPostProcessorsFactory类型参数。这个类的无参构造是在SpringApplication实例化时被调用的。这里主要是要理解、熟悉函数作为参数传递的用法。这个函数实际传的值是org.springframework.boot.env.EnvironmentPostProcessorsFactory#fromSpringFactories(),

下面就是执行监听器回调,最后调用了this.postProcessorsFactory.apply(classLoader);来得到一个EnvironmentPostProcessorsFactory类型实例,其实际类型其实是ReflectionEnvironmentPostProcessorsFactory

public class EnvironmentPostProcessorApplicationListener implements SmartApplicationListener, Ordered {private final Function<ClassLoader, EnvironmentPostProcessorsFactory> postProcessorsFactory;/*** Create a new {@link EnvironmentPostProcessorApplicationListener} with* {@link EnvironmentPostProcessor} classes loaded through {@code spring.factories}.*/public EnvironmentPostProcessorApplicationListener() {this(EnvironmentPostProcessorsFactory::fromSpringFactories, new DeferredLogs());}EnvironmentPostProcessorApplicationListener(Function<ClassLoader, EnvironmentPostProcessorsFactory> postProcessorsFactory, DeferredLogs deferredLogs) {this.postProcessorsFactory = postProcessorsFactory;this.deferredLogs = deferredLogs;}@Overridepublic void onApplicationEvent(ApplicationEvent event) {if (event instanceof ApplicationEnvironmentPreparedEvent) {onApplicationEnvironmentPreparedEvent((ApplicationEnvironmentPreparedEvent) event);}if (event instanceof ApplicationPreparedEvent) {onApplicationPreparedEvent();}if (event instanceof ApplicationFailedEvent) {onApplicationFailedEvent();}}private void onApplicationEnvironmentPreparedEvent(ApplicationEnvironmentPreparedEvent event) {ConfigurableEnvironment environment = event.getEnvironment();SpringApplication application = event.getSpringApplication();for (EnvironmentPostProcessor postProcessor : getEnvironmentPostProcessors(application.getResourceLoader(),event.getBootstrapContext())) {postProcessor.postProcessEnvironment(environment, application);}}List<EnvironmentPostProcessor> getEnvironmentPostProcessors(ResourceLoader resourceLoader,ConfigurableBootstrapContext bootstrapContext) {ClassLoader classLoader = (resourceLoader != null) ? resourceLoader.getClassLoader() : null;EnvironmentPostProcessorsFactory postProcessorsFactory = this.postProcessorsFactory.apply(classLoader);return postProcessorsFactory.getEnvironmentPostProcessors(this.deferredLogs, bootstrapContext);}
}

还是读取spring.factories文件得到 EnvironmentPostProcessor用于可扩展的设计。

这个类的方法不好理解,这里用了Instantiator,构建Instantiator时第二个参数是一个方法,告诉Instantiator,在创建EnvironmentPostProcessor实例的时候,如果构造函数或setter方法中有DeferredLogFactory类型的参数,则使用logFactory作为实际值,下面几个add作用也是一样。

class ReflectionEnvironmentPostProcessorsFactory implements EnvironmentPostProcessorsFactory {@Overridepublic List<EnvironmentPostProcessor> getEnvironmentPostProcessors(DeferredLogFactory logFactory,ConfigurableBootstrapContext bootstrapContext) {Instantiator<EnvironmentPostProcessor> instantiator = new Instantiator<>(EnvironmentPostProcessor.class,(parameters) -> {parameters.add(DeferredLogFactory.class, logFactory);parameters.add(Log.class, logFactory::getLog);parameters.add(ConfigurableBootstrapContext.class, bootstrapContext);parameters.add(BootstrapContext.class, bootstrapContext);parameters.add(BootstrapRegistry.class, bootstrapContext);});return (this.classes != null) ? instantiator.instantiateTypes(this.classes): instantiator.instantiate(this.classLoader, this.classNames);}}

org.springframework.boot.context.config.ConfigDataEnvironment#processAndApply


http://www.mrgr.cn/news/7101.html

相关文章:

  • 25届网安秋招,信息泄露常问之配置信息泄露
  • 外网爆火的LLM应用手册来了!内行人都在学的大模型黑书,豆瓣评分高达9.9!!!
  • 【Python机器学习】NLP概述——自然语言智商
  • 【OpenFeign】OpenFeign指定url方式调用
  • K8S 基于本地存储的一主一从 MySQL 架构
  • 程序员的恐惧之源-改需求
  • Flat Ads:全球金融应用的营销投放洞察
  • 金融帝国实验室(Capitalism Lab)官方技术支持中文汉化包_v4.09
  • 一文彻底搞懂CNN - 模型架构(Model Architecture)
  • Springsecurity 自定义AuthenticationManager
  • web测试之功能测试常用的方法有哪几种?有什么要点要注意?
  • 【JavaEE】深入MyBatis:动态SQL操作与实战项目实现指南
  • 前端打字效果
  • RKNN在转换过程中的均值和方差设置问题
  • 【图解秒杀系列】秒杀技术点——多级缓存、分层过滤
  • STM32按键控制小灯—HAL库
  • 《黑神话:悟空》到底是用什么语言开发的
  • 2024年TikTok的最新操作方案及变现方式
  • 书籍字符串的统计字符串(5)0823
  • sql 如何在查询时移除某一行数据以及这一行的上一行数据