@ConfigurationProperties 注解原理

news/2024/4/19 0:17:25

前言

@ConfigurationProperties注解是 SpringBoot 提供的一种更加便捷来处理配置文件中的属性值的方式,可以通过自动绑定和类型转换等机制,将指定前缀的属性集合自动绑定到一个Bean对象上。

加载原理

在 Springboot 启动流程加载配置的 prepareEnvironment() 方法中,有一个重要的步骤方法 bindToSpringApplication(environment),它的作用是将配置文件中的属性值绑定到被 @ConfigurationProperties 注解标记的 Bean对象中。但此时这些对象还没有被 Spring 容器管理,因此无法完成属性的自动注入。那么这些Bean对象又是什么时候被注册到 Spring 容器中的呢?

这就涉及到了 ConfigurationPropertiesBindingPostProcessor 类,它是 Bean后置处理器,负责扫描容器中所有被 @ConfigurationProperties 注解所标记的 Bean对象。如果找到了,则会使用 Binder 组件将外部属性的值绑定到它们身上,从而实现自动注入。

  • bindToSpringApplication 主要是将属性值绑定到 Bean 对象中;
  • ConfigurationPropertiesBindingPostProcessor 负责在 Spring 容器启动时将被注解标记的 Bean 对象注册到容器中,并完成后续的属性注入操作;

从springboot程序启动看配置初始化

Springboot 程序启动加载流程里,会执行SpringApplication.run中的prepareEnvironment()方法进行配置的初始化,那初始化过程每一步都做了什么呢?

private ConfigurableEnvironment prepareEnvironment(SpringApplicationRunListeners listeners,DefaultBootstrapContext bootstrapContext, ApplicationArguments applicationArguments) {/** * 1、创建 ConfigurableEnvironment 对象:首先调用 getOrCreateEnvironment() 方法获取或创建* ConfigurableEnvironment 对象,该对象用于存储环境参数。如果已经存在 ConfigurableEnvironment 对象,则直接使用它;否则,根据用户的配置和默认配置创建一个新的。*/ConfigurableEnvironment environment = getOrCreateEnvironment();/*** 2、解析并加载用户指定的配置文件,将其作为 PropertySource 添加到环境对象中。该方法默认会解析 application.properties 和 application.yml 文件,并将其添加到 ConfigurableEnvironment 对象中。* PropertySource 或 PropertySourcesPlaceholderConfigurer 加载应用程序的定制化配置。*/configureEnvironment(environment, applicationArguments.getSourceArgs());// 3、加载所有的系统属性,并将它们添加到 ConfigurableEnvironment 对象中ConfigurationPropertySources.attach(environment);// 4、通知监听器环境参数已经准备就绪listeners.environmentPrepared(bootstrapContext, environment);/***  5、将默认的属性源中的所有属性值移到环境对象的队列末尾,这样用户自定义的属性值就可以覆盖默认的属性值。这是为了避免用户无意中覆盖了 Spring Boot 所提供的默认属性。*/DefaultPropertiesPropertySource.moveToEnd(environment);Assert.state(!environment.containsProperty("spring.main.environment-prefix"),"Environment prefix cannot be set via properties.");// 6、将 Spring Boot 应用程序的属性绑定到环境对象上,以便能够正确地读取和使用这些配置属性bindToSpringApplication(environment);// 7、如果没有自定义的环境类型,则使用 EnvironmentConverter 类型将环境对象转换为标准的环境类型,并添加到 ConfigurableEnvironment 对象中。if (!this.isCustomEnvironment) {EnvironmentConverter environmentConverter = new EnvironmentConverter(getClassLoader());environment = environmentConverter.convertEnvironmentIfNecessary(environment, deduceEnvironmentClass());}// 8、再次加载系统配置,以防止被其他配置覆盖ConfigurationPropertySources.attach(environment);return environment;
}

看看它的配置加载流程步骤:

  • 创建 环境对象 ConfigurableEnvironment 用于存储环境参数;
  • configureEnvironment 方法加载默认的 application.properties 和 application.yml 配置文件;以及用户指定的配置文件,将其封装为 PropertySource 添加到环境对象中;
  • attach(): 加载所有的系统属性,并将它们添加到环境对象中;
  • listeners.environmentPrepared(): 发送环境参数配置已经准备就绪的监听通知;
  • moveToEnd(): 将 系统默认 的属性源中的所有属性值移到环境对象的队列末尾,这样用户自定义的属性值就可以覆盖默认的属性值。
  • bindToSpringApplication: 应用程序的属性绑定到 Bean 对象上;
  • attach(): 再次加载系统配置,以防止被其他配置覆盖;

上边的配置加载流程中,各种配置属性会封装成一个个抽象的数据结构 PropertySource中,这个数据结构代码格式如下,key-value形式。

public abstract class PropertySource<T> {protected final String name; // 属性源名称protected final T source; // 属性源值(一个泛型,比如Map,Property)public String getName();  // 获取属性源的名字  public T getSource(); // 获取属性源值  public boolean containsProperty(String name);  //是否包含某个属性  public abstract Object getProperty(String name);   //得到属性名对应的属性值   
} 

PropertySource 有诸多的实现类用于管理应用程序的配置属性。不同的 PropertySource 实现类可以从不同的来源获取配置属性,例如文件、环境变量、命令行参数等。其中涉及到的一些实现类有:

关系图

  • MapPropertySource: Map 键值对的对象转换为 PropertySource 对象的适配器;
  • PropertiesPropertySource: Properties 对象中的所有配置属性转换为 Spring 环境中的属性值;
  • ResourcePropertySource: 从文件系统或者 classpath 中加载配置属性,封装成 PropertySource对象;
  • ServletConfigPropertySource: Servlet 配置中读取配置属性,封装成 PropertySource 对象;
  • ServletContextPropertySource: Servlet 上下文中读取配置属性,封装成 PropertySource 对象;
  • StubPropertySource: 是个空的实现类,它的作用仅仅是给 CompositePropertySource 类作为默认的父级属性源,以避免空指针异常;
  • CompositePropertySource: 是个复合型的实现类,内部维护了 PropertySource集合队列,可以将多个 PropertySource 对象合并;
  • SystemEnvironmentPropertySource: 操作系统环境变量中读取配置属性,封装成 PropertySource 对象;

上边各类配置初始化生成的 PropertySource 对象会被维护到集合队列中。

List<PropertySource<?>> sources = new ArrayList<PropertySource<?>>()

配置初始化完毕,应用程序上下文AbstractApplicationContext会加载配置,这样程序在运行时就可以随时获取配置信息了。

 private void prepareContext(DefaultBootstrapContext bootstrapContext, ConfigurableApplicationContext context,ConfigurableEnvironment environment, SpringApplicationRunListeners listeners,ApplicationArguments applicationArguments, Banner printedBanner) {// 应用上下文加载环境对象context.setEnvironment(environment);postProcessApplicationContext(context);.........}

3、读取配置

看明白上边配置加载的流程,其实读取配置就容易理解了,无非就是遍历队列里的PropertySource,拿属性名称name匹配对应的属性值sourcePropertyResolver是获取配置的关键类,其内部提供了操作PropertySource 队列的方法,核心方法getProperty(key)获取配置值,看了下这个类的依赖关系,发现 Environment 是它子类。

那么直接用 PropertyResolver 来获取配置属性其实也是可以的,到这我们就大致明白了 Springboot 配置的加载和读取了。

@Slf4j
@SpringBootTest
public class EnvironmentTest {@Resourceprivate PropertyResolver env;@Testpublic void var1Test() {String var1 = env.getProperty("env101.var1");log.info("Environment 配置获取 {}", var1);}
}

http://www.ppmy.cn/news/451601.html

相关文章

PyTorch 深度学习 || 2. 全连接网络 | Ch2.3 PyTorch 全连接自编码网络的无监督学习

PyTorch 全连接自编码网络的无监督学习 文章目录 PyTorch 全连接自编码网络的无监督学习1. 数据去噪1.1 计算库和数据准备工作1.2 构建自编码网络1.3 调用主函数1.4 可视化 2. 数据的重建与降维2.1 计算模块和数据的准备2.2 自编码网络数据准备2.3 自编码网络的构建2.4 自编码网…

Android 使用adb修改手机分辨率、dpi

为了适配不同尺寸屏幕的手机&#xff0c;最简单的方式就是通过adb修改分辨率和dpi adb安装 Android Studio 安装adb&#xff08;Android Debug Bridge&#xff09; adb官网下载 https://developer.android.com/studio/releases/platform-tools?hlzh-cn adb修改size 查看…

ufs2.0测试软件,三星S8被爆混用UFS闪存 如何测试是UFS 2.0还是UFS 2.1?

华为 “闪存门”事件从 4 月份开始至今并未平息&#xff0c;主要还是因为消费者对华为的官方说法并不满意&#xff0c;因为华为一直强调自己不背锅&#xff0c;毕竟是供应链 UFS 闪存缺货造成的影响。关键是华为还认为 eMMc 与 UFS 不同闪存不会影响系统体验一致性。不得不说&a…

三星手机动态修改分辨率信息

较早前文章介绍了如何在安卓手机上安装激活XPOSED框架&#xff0c;XPOSED框架的极强的功能各位都清楚&#xff0c;能够不修改应用程序的前提下&#xff0c;修改系统内核的参数&#xff0c;好比在某些应用领域&#xff0c;各位需要修改手机的某个系统参数&#xff0c;这时就需要…

卡位高端:三星S8卖断货折射市场节点

5月18日晚上&#xff0c;三星在古北水镇长城剧场发布新旗舰机型Galaxy S8|S8的时候&#xff0c;高东真并没有想到这款手机的上市流程&#xff0c;会在半月之后进行“延长预约日期并增加购机优惠”方面的调整。 尤其是这种轻易调整即可导致营销成本剧升、供货量面临巨大考验的策…

高通骁龙845的android手机有哪些,2018年骁龙845手机有哪些?骁龙845手机怎么样?...

2018骁龙845手机有哪些&#xff1f;骁龙845手机怎么样&#xff1f;在今年12月末高通正式确定了骁龙845处理器的成功研发&#xff0c;对于手机控来说&#xff0c;这款骁龙845处理器会应用在哪些手机上无疑是非常令人期待和关注的&#xff0c;这里提供部分可能信息&#xff0c;希…

屏幕小于6英寸的手机_6英寸屏幕真的大么?你可能对“全面屏”有什么误解!详解全面屏手机那些事...

6英寸屏幕真的大么&#xff1f;你可能对“全面屏”有什么误解&#xff01;详解全面屏手机那些事 2018-05-15 10:31:35 225点赞 278收藏 118评论 小编注&#xff1a;想获得更多专属福利吗&#xff1f;金币加成、尊享众测、专属勋章、达人福利任务你想要吗&#xff1f;如果想要&a…

4g运行内存手机还能用多久_看完就明白:目前手机运行内存超过4G就是浪费

腾讯数码讯(文心)据Android Central网站报道&#xff0c;vivo 乎要推出一款运行内存容量高达10GB的手机。这意味着这款手机运行内存容量堪比许多游戏PC&#xff0c;比大多数手机多约6GB。这让许多手机用户都感到迷惑不解&#xff0c;心里直嘀咕&#xff1a;手机真的需要10GB运行…

三星android9更快么,三星S9将会成为最快Android手机 有6大要点你必须知道

腾讯数码讯(云之外)三星将会在2月25日推出Galaxy S9&#xff0c;离现在只有不到2周的时间了&#xff0c;我们已经对手机的性能有了一些了解。 如果S9安装高通骁龙845芯片&#xff0c;它的速度将会比S8快30%&#xff0c;S8是三星目前最好的手机。美国版S9会安装骁龙845&#xff…

步华为后尘?三星S8被爆也混用内存!

目前还是等三星官方回应吧&#xff0c;希望国行机不会出现这种情况。 科客 2017/05/07 17:04评论(5) 收藏(3) 18.2W字体&#xff1a;宋 华为P10深陷“闪存门”已有一段时间&#xff0c;虽然华为官方多次出面处理&#xff0c;甚至一向态度强硬的余承东也表示积极反思&#xff0…

深度体验:6.2英寸大屏手机三星S8+ 让你玩到爽

前不久&#xff0c;三星S8和三星S8两款手机的国行版在国内开售了&#xff0c;作为三星今年主打的旗舰系列产品&#xff0c;这两款手机可以说是非常值得拥有的&#xff0c;特别是屏幕更大、电池容量更高的三星S8更是受到了国内消费者的喜爱&#xff0c;虽然其价格比三星S8稍贵了…

利用一个竞态漏洞root三星s8的方法

作者&#xff1a;zjqIceSword Lab来源&#xff1a;http://www.iceswordlab.com/2018/04/20/samsung-root/ 在安卓阵营中&#xff0c;三星手机可以说是最重视安全的了&#xff0c;各种mitigation技术都是早于官方系统应用到自己手机上&#xff0c;并且加入了KNOX技术&#xff0…

s8 android调用相机,改善画质无需硬件:当Galaxy S8遇上谷歌Pixel相机

我们都知道,三星从 S6 时期起就已经有了还算不错的成像算法,并且 S8 上搭载的高通骁龙 835 处理器还内置了 Spectra 180 ISP(双图像信号处理单元),能提供更纯净和清晰的成像。那么,当拥有 Spectra 180 ISP 的 S8 用上了谷歌 HDR+ 算法后,表现究竟会不会比三星自带的相机好…

三星s8怎么分屏操作_三星Z Fold2双屏拍照体验:连拍照的过程都这么好玩?

[PConline 专业评测]随着智能手机的普及和手机功能的日益丰富&#xff0c;人们选择一款手机不再仅仅追求性能、屏幕和续航这些可以最直观被感受到的配置参数&#xff0c;而是把更多的决定权交给了拍照、工艺、手感等曾被忽视多时的深度级体验。 对于大多数人来说&#xff0c;不…

三星Galaxy S8 刷机经验记录

这段时间用上了三星S8&#xff0c;由于原生系统太耗电&#xff0c;所以萌生了root的想法。写这篇博客记录下这段时间的各种尝试。 Root过程说明&#xff1a; 友情提示&#xff0c;道路千万条&#xff0c;安全第一条。开始捣鼓手机之前请一定准备好官方的救砖包。 1.解锁手机&am…

三星s8怎么分屏操作_领跑折叠屏手机 三星Galaxy Z Fold2 5G魅力何在

进入全面屏时代&#xff0c;手机发展慢慢进入到一个瓶颈中&#xff0c;我们看到刘海屏、水滴屏、挖孔屏轮番演绎着屏幕的进化史&#xff0c;虽然屏幕越来越大&#xff0c;边框越来越窄&#xff0c;但从体验上来说&#xff0c;并没有发生太多变化。 不过&#xff0c;折叠屏手机…

三星s8自带测试硬件软件,三星s8硬件测试指令 | 手游网游页游攻略大全

发布时间&#xff1a;2016-06-09 三星S8是三星目前在准备中的旗舰机,应该在明年上市.三星S8目前有不少屏幕配置曝光.三星S8将配备什么样的屏幕配置呢?99安卓网小编艾米分享下三星S8屏幕配置消息. 三星S8渲染图 近期三星公布一项新技术,名为“Bio ... 标签&#xff1a; 三星S8 …

【每日挠头算法题(9)】二叉树的直径|二叉树的层序遍历

文章目录 一、二叉树的直径思路&#xff1a;二叉树的深度优先搜索具体代码如下&#xff1a; 二、二叉树的层序遍历思路&#xff1a;借助队列实现具体代码如下&#xff1a; 总结&#xff1a; 一、二叉树的直径 点我直达~ 思路&#xff1a;二叉树的深度优先搜索 根据题目要求&a…

全网超全,接口测试用例设计——常见问题和风险,测试不背锅...

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 接口测试用例设计…

知识复盘(Session、Mysql、Servlet、Jsp、SSM)

一、会话跟踪技术(Session Tracking&#xff09; 1.为什么会出现会话机制? 目前主流的通讯方式就是客户端和服务端之间进行通信&#xff0c;而这种通信是通过Http协议实现的&#xff0c;但Http协议本身是无状态的&#xff0c;所以客户端每发送一次请求到服务器都会被当做一个…