目录

1.问题起源

2.深入探究:Spring Boot 配置加载顺序

1.命令行参数

2.Java 系统属性

3.操作系统环境变量 (Environment Variables)

4.bootstrap.yml

5.外部 application 配置文件 (./config/application.yml)

6.外部 application 配置文件 (./application.yml)

7.Nacos Server 拉取的配置

8.classpath:/config/ 包内的 application.yml

9.classpath:/ 根目录下的 application.properties 或 application.yml

3.实例分析

4.总结


最近在维护一个老项目时,遇到了一个关于配置加载顺序的有趣问题,最终让我重新审视了 Spring Boot 的配置加载机制。分享出来,希望能帮助到同样遇到困惑的朋友。

1.问题起源

事情是这样的:我修改完代码后准备打包给现场同事部署。这时想到一个问题:我本地的 application.yml 里配置的都是测试环境的地址(如数据库、Redis),如果直接打包给他,应用能正常启动吗?

同事说:“没事,直接打就行。”我当时没多想,觉得可能是现场用了 Nacos 配置中心或者有外部配置文件覆盖。

后来又遇到一个需要根据配置项 (enableProduct: true/false) 进行判断的功能。为了确认线上环境的值,我去问了现场同事。他的回答让我大跌眼镜——他们的启动命令是这样的:

nohup /usr/local/jdk/bin/java -jar survey-supervision-api-1.0-SNAPSHOT.jar >strat.log 2>&1 &

这不就是最简单的 java -jar 启动吗?没有指定任何外部配置文件!按理说,它应该会读取打包在 JAR 内的 application.yml,而这个文件里是测试环境的配置,项目怎么可能正常连接现场的数据源呢?

带着疑问,我让他远程查看了服务器上的部署目录。结果发现,jar 包所在的目录下(/path/to/your/app/)赫然躺着一个 application.yml 文件!打开一看,里面全是现场环境的正确配置。原来,Spring Boot 自动加载了这个外部配置文件,覆盖了 JAR 包内的默认配置。

2.深入探究:Spring Boot 配置加载顺序

这个发现让我意识到,我对 Spring Boot 的配置优先级掌握得不够全面。赶紧查阅官方文档,梳理了一下完整的配置加载顺序。这对于排查“为什么我的配置不生效”这类问题至关重要。

Spring Boot 的配置加载遵循一个优先级顺序,从高到低如下(请注意,对于 Spring Cloud Alibaba Nacos Config 2021.x 版本,Nacos 配置的优先级低于本地外部配置):

1.命令行参数

最高优先级,直接通过命令行传递的参数,例如 --server.port=8080

2.Java 系统属性

通过 -D 设置的 JVM 系统属性,例如 -Dspring.profiles.active=prod

3.操作系统环境变量 (Environment Variables)

系统级别的环境变量

4.bootstrap.yml

在主应用上下文 (Main Context) 之前加载的引导上下文 (Bootstrap Context) 配置文件。主要用于配置 Spring Cloud 相关组件(如 Nacos Server 地址等)

5.外部 application 配置文件 (./config/application.yml)

位于 JAR 包同目录下的 config 子目录中的配置文件。这是优先级最高的本地外部配置文件

6.外部 application 配置文件 (./application.yml)

位于 JAR 包同目录下的配置文件

7.Nacos Server 拉取的配置

在 2021.x 版本中,Nacos Config 从服务器获取的配置(通过 shared-configs 或 ext-config 加载)的优先级低于 步骤 5 和 6 的本地外部配置文件。注意:在更新的版本中,这一行为可能通过 refreshable-dataids 或其他机制有所改变,但在此版本中,本地外部配置更胜一筹,没有具体测试,仅供参考

8.classpath:/config/ 包内的 application.yml

位于 JAR 包内部 resources/config/ 目录下的配置文件

9.classpath:/ 根目录下的 application.properties 或 application.yml

位于 JAR 包内部 resources 根目录下的配置文件

3.实例分析

假设你有以下配置:

  • JAR 包同目录下 (/app/) 的 application.ymldatabase.url: jdbc:mysql://prod-db:3306/mydb
  • JAR 包内部 (resources/application.yml) 的 application.ymldatabase.url: jdbc:mysql://test-db:3306/mydb

根据优先级顺序,步骤 6 (./application.yml) 的优先级高于 

步骤 9 (classpath:/application.yml),

因此应用最终会使用 jdbc:mysql://prod-db:3306/mydb 连接数据库。

4.总结

这个小插曲让我深刻体会到,理解 Spring Boot 的配置加载顺序对于项目部署和问题排查至关重要。它不仅解释了为什么简单的 java -jar 命令就能让应用连接到正确的现场环境,也为后续可能出现的配置覆盖问题提供了排查方向。

下次当你修改了配置却发现不起作用时,不妨按照这个优先级列表检查一下,看看是不是被更高优先级的配置给覆盖了。



 

Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐