今天我们要聊的这个问题,可能工作5年的资深程序员也不一定搞得很清楚,但是我敢保证在开发 Web 应用过程中大家都遇到过。

这个问题就是: Spring Boot 应用程序读取配置属性时,不同配置源的优先级是个啥情况?

那如果你对这个问题没啥概念,我给大家说几个场景,你肯定就明白了?

  1. 应用程序的数据库配置,我们一般都是通过配置文件配置的?不会有人直接硬编码写的吧;

  2. 应用开发中往往都需要加一些开关来控制业务逻辑,比如新功能灰度之类的场景;

  3. 开发、测试、生产环境需要不同的值,这种变量一般也都是通过外置配置来读取的,不会直接写死的;

我想上面这几种场景,搞过 Java 开发的总归会遇到的,今天我们要聊的就是这些外置的配置属性,配置在不同的地方,如果属性名一样的情况下,到底谁的优先级高?也可以说配置在高优先级地方的属性值会覆盖低优先级位置的同名属性值。

说实话,这个问题我身边很多工作了多年的资深开发都没有搞明白,不过这个并不影响他们开发,大不了调试一波嘛,就是多费点时间。但是也有特别骚的情况,他们也头大。

比如生产环境莫名其妙的出了问题,排查是因为一个配置属性值不对导致的,但是测试环境看了没问题,然后项目中的配置文件配置的也没问题,这种就很烦人了。

排查到最后一般就会发现:生产环境的启动命令加了命令行参数或者 JVM 系统属性,比这还骚的就是配到了系统的环境变量里面。。

那今天这个问题搞懂了,就有以下几个好处:

  1. 可以帮助你高效的开发出符合预期的应用程序;

  2. 在排查一些老代码导致的异常时,多一个排查思路,看看是否是不同环境的属性配置不同(经常有一些老项目的属性值是配置在环境变量里,覆盖了代码里面的属性配置);

  3. 提高开发效率(在不改项目配置的情况下,通过高优先级的属性源覆盖对应的属性)

Spring Boot 常用的属性源

下面列举出我们平时常用的一些配置属性源:

这些属性源其实我已经按照优先级从高到低的顺序排列了,也就是说命令行参数的优先级最高,其次是 JVM 系统属性,默认属性优先级最低,同名属性将会遵循高优先级覆盖掉低优先级。

这其实就是本文的最终结论了,后面就是介绍各种属性源如何设置,进行实操验证了。你如果不想往后看了,直接收藏这张图片也是可以的哦~

这些属性配置的方法部分小伙伴可能没有用过,接下来我们用一个例子来实战演示下,也推荐你动手实践,试试结论是否正确,这样理解记忆会更加深刻。

验证配置属性的优先级

为了能够清晰高效的达到我们验证各个属性源配置属性优先级的目的,这里的思路就是:先在低优先级的属性源配置,然后配置高优先级,如果覆盖了就说明我们的结论没毛病。

首先我们使用 Spring Boot 快速写一个简单的 Web 接口,然后直接返回配置的属性名:

@RestController
public class ReadingListController {// 获取属性配置的类@Resourceprivate MyProperties myProperties;@GetMapping("/getMaxValue")public String getProperties () {return "配置的属性值 = " + myProperties.getMaxValue();}
}

上面我们使用了一个专门用来获取配置属性的 Bean,不建议直接在 Controller 引用属性,这个大家平时在开发中也要注意下:

@Component
@ConfigurationProperties(prefix= "my" )
@Data
public class MyProperties {// 默认属性值private int maxValue= 0;}

那上面的代码就是我们测试所需要的全部代码了,接下来我们从最低优先级的属性源开始配置。

默认属性

这个不用多说,就是直接在 Java 代码中声明变量时赋予的值;

启动应用程序后,访问我们的测试接口:http://localhost:8000/getMaxValue

通过 @PropertySource 标注的属性源

这种属性配置的方法我们一般也经常用,就是自定义一个配置文件,然后用 @PropertySource 注解来指定加载。

上面的代码,就会加载我们定义在 classpath 路径下的 my.properties 文件了。我们在自定义的属性配置文件 my.properties 中添加配置属性:

my.maxValue=1

然后重启应用,访问我们的测试接口,得到的输出如下:

这就证明了 @PropertySource 属性源配置覆盖了默认配置。

application.properties配置文件

Spring Boot 应用程序,默认会加载 classpath 路径下 application.propertiesapplication.yml 文件中配置的属性。这也是我们开发时最常用的属性配置源了。

在重启应用,访问我们的测试接口,就会得到结果值 2 了。说明应用内的 application.properties 文件中配置的属性优先级高于 @PropertySource 指定的自定义配置文件。

这里需要注意,如果 classpath 路径下同时存在 application.yml 和 application.properties 文件,那么 application.yml 文件中的属性优先级高于 application.properties,这一点大家也可以自己测试下。

操作系统环境变量

这是一种骚操作了,在不同的环境设置了不同的操作系统环境变量,任你看代码找破天也是一头雾水。所以下次出现不同环境配置属性值不符合预期的场景,操作系统环境变量记着检查下。

这里我使用的 zsh,可以使用 export 来设置临时的操作系统环境变量,当然 bash 也可以这样配置。

export my_maxvalue=3

细心的同学发现了,变量的命令我使用了下划线而不是点,这是因为操作系统对变量名称的要求。

然后我们将应用打包,我这里使用的 gradle 来构建项目,只需要执行:gradle build , Spring Boot  提供的 gradle 插件就会帮我们将所有需要的依赖打包到一起,得到一个可执行的 jar 包。

然后我们启动应用程序:java -jar build/libs/spring-road02-0.0.1-SNAPSHOT.jar

访问测试接口得到的值就是3了。

结论证明:操作系统环境变量配置的属性优先级又高于上面我们所列举的。

JVM系统属性

这也是生产环境使用最多的一种差异化属性设置方式,在应用程序的启动脚本命令中指定属性值,好处就是其他人不能随意修改,一般只能运维人员来编写的。常见于配置一些影响应用程序运行稳定性的参数,比如内存分配、GC参数等的配置。

还是使用上面我们打好的 jar 包,在运行时增加 JVM 系统属性即可:

java -Dmy.maxvalue=4 -jar build/libs/spring-road02-0.0.1-SNAPSHOT.jar

然后访问测试接口得到的值就变为了4。

命令行属性配置

这个和 JVM 系统属性配置的使用场景差不多,只不过设置方式有点区别,直接看下命令行启动配置就明白了:

java -Dmy.maxvalue=4 -jar build/libs/spring-road02-0.0.1-SNAPSHOT.jar --my.maxvalue=5

启动后,我们继续访问测试接口看看结果:

结果证明,命令参数的优先级比 JVM 系统属性优先级高,会将其覆盖。

总结

通过今天的实践学习,大家应该对 Spring Boot 属性配置常见的几种来源有了更加清晰的认识,并且通过实验测试了它们具体的优先级。我们再来汇总整理下:

按照优先级的高低从上往下排列,也就是说命令行参数配置的属性优先级最高,会覆盖其它属性源的配置,以此类推,记不住的小伙伴可以收藏下,以备不时之需。

今天就先聊到这里,更多关于 Spring 相关的内容,也在持续更新中,敬请关注!

有道无术,术可成;有术无道,止于术

欢迎大家关注Java之道公众号

好文章,我在看❤️

Spring Boot 属性配置你所不知道的细节相关推荐

  1. Spring Boot 属性配置和使用

    spring Boot 允许通过外部配置让你在不同的环境使用同一应用程序的代码,简单说就是可以通过配置文件来注入属性或者修改默认的配置. Spring Boot 系列 Spring Boot 入门 S ...

  2. 8.1、Spring Boot 属性配置

    1.属性生效的优先级 默认属性(硬编码) @PropertySource 绑定的属性 JAR 包内的 application.properies JAR 包外的 application.properi ...

  3. 关于Istio 1.1,你所不知道的细节

    本文整理自Istio社区成员Star在 Cloud Native Days China 2019 北京站的现场分享 第1则 主角 Istio Istio作为service mesh领域的明星项目,从2 ...

  4. 重新认识Windows计算器Calc(MatLab计算替代品)——你所不知道的细节

     笔者:IBMInfo78@126.com Windows 计算器Calc(Windows 7版本)是一个常用的工具,也是一款非常专业.优秀的基础计算程序.它有四种计算场景,分别为:标准型.科学型.程 ...

  5. Android Context完全解析,你所不知道的Context的各种细节

    转载请注明出处:http://blog.csdn.net/guolin_blog/article/details/47028975 前几篇文章,我也是费劲心思写了一个ListView系列的三部曲,虽然 ...

  6. Spring Boot 你所不知道的超级知识学习路线清单

    因而 Spring Boot 应用本质上就是一个基于 Spring 框架的应用,它是 Spring 对"约定优先于配置"理念的最佳实践产物,它能够帮助开发者更快速高效地构建基于 S ...

  7. 被低估的css滤镜,你所不知道的 CSS 滤镜技巧与细节

    本文主要介绍 CSS 滤镜的不常用用法,希望能给读者带来一些干货! 系列 CSS 文章汇总在我的 Github ,持续更新,欢迎点个 star 订阅收藏. OK,下面直接进入正文.本文所描述的滤镜,指 ...

  8. JSP如何获取Spring Boot的配置属性

    在Spring Boot + JSP的应用中,一般使用Session作为用户身份的认证, 有时候在JSP页面中需要读取配置在Spring Boot 的配置文件(比如application.proper ...

  9. Spring Boot自动配置原理

    要了解Spring Boot的自动配置首先我需要先了解Spring Boot的两个机制,一个是配置文件如何进入到系统变成属性,二是如何将这些属性加入到容器中. 首先我们需要有一个组件,这个组件中的属性 ...

最新文章

  1. 研究人员发现物联网存在安全漏洞
  2. 计算机研究生自我介绍,计算机专业研究生英文的自我介绍
  3. 张一鸣活捉上班摸鱼员工遭怒怼:不爽退群啊!
  4. 华强北出租5G手机,半小时3块钱,双11“秒杀利器”,十秒九中!
  5. android音量加减驱动,android下调试声卡驱动之概述
  6. Python入门--获取指定目录下的所有.py文件
  7. Shared library can't open object
  8. 论文笔记_S2D.14-2014-NIPS_利用多尺度深度网络从单张图像预测深度图
  9. linux和windows时间同步问题(UTClocaltime)
  10. cad手机看图 android,CAD手机看图
  11. 1230v3配服务器内存性能提升,E3 1230 V3四核3.7G睿频福利教程及评测
  12. 【移动安全基础篇】——02、APP内付破解
  13. mw150um 驱动程序win10_水星MW150UM 1.0无线网卡驱动
  14. 【染上你的颜色】MMD动作+镜头下载
  15. 第二章作业习题答案续
  16. Shell If Else语句 数学运算 与 逻辑运算
  17. 《CSS揭秘》实用技巧总结
  18. MySQL数据库基础表格——增删改查(下)
  19. 【面试篇】ConcurrentHashMap1.7和1.8详解对比
  20. 1-智能QOS方案介绍

热门文章

  1. 简单的反U盘病毒(删除不了的畸形文件夹)
  2. 三星mega2 android os,GALAXY MEGA2
  3. 神经网络python识别词语_请教关于python的手写数字识别神经网络问题~~~~
  4. 数据结构之图的存储结构:邻接多重表
  5. LeetCode篇:1(两数之和)
  6. (计算机组成原理)第七章输入和输出系统-第二节1:外部设备之输入和输出设备(键盘鼠标、显示器和打印机)
  7. 4-5:TCP协议之确认应答(ACK)机制和超时重传机制
  8. 如何配置java环境变量
  9. Gitlab自动触发Jenkins构建项目
  10. 1163 最高的奖励(贪心+优先队列)