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

Spring Boot的配置文件加载顺序和规则

理解Spring Boot的配置文件加载顺序和规则至关重要,因为它直接影响到应用的配置覆盖和不同环境的部署。我会为你进行详细的说明,并附上具体事例。

核心概念

Spring Boot使用一个非常特别的 PropertySource 顺序来允许合理的配置覆盖。优先级从高到低排列,高优先级的配置会覆盖低优先级的配置。

配置文件加载顺序(优先级从高到低)

这个顺序是理解配置覆盖的关键。想象一下,列表顶部的配置源会“覆盖”它下方的所有配置源。

  1. DevTools全局设置 (~/.spring-boot-devtools.properties, 当激活了DevTools时)
  2. 测试环境上的 @TestPropertySource 注解
  3. 测试环境上的 properties 属性 (@SpringBootTest 注解等)
  4. 命令行参数 (e.g., java -jar app.jar --server.port=8087)
  5. 来自 SPRING_APPLICATION_JSON 的属性 (内嵌在环境变量或系统属性中的JSON)
  6. ServletConfig 初始化参数
  7. ServletContext 初始化参数
  8. JNDI属性 (来自 java:comp/env)
  9. Java系统属性 (System.getProperties())
  10. 操作系统环境变量
  11. RandomValuePropertySource (只包含 random.* 的属性)
  12. 应用 jar 包外部的 Profile-specific 配置文件 (application-{profile}.properties.yml)
  13. 应用 jar 包内部的 Profile-specific 配置文件
  14. 应用 jar 包外部的主配置文件 (application.properties.yml)
  15. 应用 jar 包内部的主配置文件
  16. @Configuration 类上的 @PropertySource 注解
  17. 默认属性 (通过 SpringApplication.setDefaultProperties 设置)

重点规则与解释

  1. Profile-specific 覆盖 非Profile-specific:

    • 一个名为 application-prod.properties 的文件(对应 prod profile)会覆盖 application.properties 主文件中的相同属性,无论它们是在 jar 包内部还是外部。这是因为Profile-specific文件的加载位置(12,13)比主配置文件(14,15)更高。
  2. 外部文件覆盖内部文件:

    • 位于 jar 包同级目录或子目录下的 /config 文件夹中的 application.properties,会覆盖 jar 包内部application.properties。这是为什么“外部”的配置位置(12,14)优先级高于“内部”的配置位置(13,15)。
  3. 高优先级配置源覆盖低优先级配置源:

    • 命令行参数(第4位)的优先级远高于所有配置文件(12-16)。这意味着你可以用 --server.port=8087 轻松覆盖任何配置文件中的 server.port 设置。
    • 系统属性环境变量(第9,10位)的优先级也高于所有配置文件。
  4. YAML 和 Properties 等价:

    • .properties.yml 文件的加载顺序和规则是完全一样的。YAML只是提供了更简洁的层次化表达方式。

配置文件默认搜索路径(从高到低)

当一个Spring Boot应用启动时,它会从以下位置依次加载 application.propertiesapplication.yml 文件:

  1. 当前目录的 /config 子目录 (file:./config/)
  2. 当前目录 (file:./)
  3. classpath 下的 /config (classpath:/config/)
  4. classpath 根目录 (classpath:/)

规则:这个列表也是优先级顺序。1 位置的配置会覆盖 2, 3, 4 位置的相同配置;2 会覆盖 34,依此类推。

详细事例

假设我们有一个打包好的应用 myapp.jar,其内部和外部有以下文件结构:

.
├── /config/
│   └── application.properties         (端口:8081)
├── application.properties             (端口:8082)
└── myapp.jar└── BOOT-INF/classes/├── /config/│   └── application.properties (端口:8083)└── application.properties     (端口:8084)

最终生效的 server.port 是多少?

根据搜索路径的优先级:

  1. ./config/application.properties (8081) 优先级最高,它会覆盖所有其他位置的配置。
  2. 即使 jar 包内部还有配置,最终应用会使用 8081 端口。

如何覆盖?使用命令行参数:
java -jar myapp.jar --server.port=8085
此时,命令行参数(优先级第4)覆盖了所有文件配置,最终端口是 8085


Profile-specific 配置示例

假设我们有以下文件,并且激活了 prod profile (--spring.profiles.active=prod)。

  • classpath:application.properties
    app.name=MyApp
    db.host=localhost
    spring.profiles.active=dev # 默认激活dev profile
    
  • classpath:application-prod.properties
    db.host=prod-db.example.com
    db.port=3306
    
  • classpath:application-dev.properties
    db.host=dev-db.example.com
    

启动命令:
java -jar myapp.jar --spring.profiles.active=prod --app.name=OverriddenApp

最终生效的配置:

  1. app.name=OverriddenApp
    • 原因:命令行参数(高优先级)覆盖了主配置文件中的 app.name=MyApp
  2. db.host=prod-db.example.com
    • 原因prod profile 配置文件覆盖了主配置文件中的 db.host
  3. db.port=3306
    • 原因:该属性只在 application-prod.properties 中定义。
  4. spring.profiles.active=prod
    • 原因:虽然主配置文件中设置了 dev,但命令行参数优先级更高,所以最终激活的是 prod profile。注意,spring.profiles.active 本身也是一个属性,也遵循相同的覆盖规则。

注意:默认的 spring.profiles.active=dev 在主配置文件中设置,但一旦通过更高优先级的方式(如命令行)设置了profile,它就会被覆盖。Profile的激活决定了哪些 application-{profile}.properties 文件会被加载。

总结与实践建议

场景推荐方式优点
本地开发/调试classpath:/config/application-dev.properties与代码隔离,方便团队共享(不提交到git)
本地临时覆盖命令行参数 (e.g., --server.port=8087)最方便快捷
服务器通用配置Jar包外部的 ./config/application.properties优先级高,与Jar包分离,更新应用时不影响配置
服务器环境特定配置Jar包外部的 ./config/application-prod.properties同上,并且与环境绑定
敏感信息(密码等)绝不写在配置文件中。使用OS环境变量或启动参数传递。安全,不会意外泄露

希望这份详细的解释和示例能帮助你彻底掌握Spring Boot的配置加载机制!


文章转载自:

http://ar68nM1f.LqLjj.cn
http://m9erLIvg.LqLjj.cn
http://YstH025Q.LqLjj.cn
http://52rDTUSQ.LqLjj.cn
http://O9eAXEpU.LqLjj.cn
http://PUKTU7gz.LqLjj.cn
http://UQOvoNRw.LqLjj.cn
http://1oI6zmWk.LqLjj.cn
http://SJt5tA0I.LqLjj.cn
http://noHLh3nT.LqLjj.cn
http://spUDABga.LqLjj.cn
http://PX3SM1Xi.LqLjj.cn
http://WC0nfEm4.LqLjj.cn
http://wfyXyA5o.LqLjj.cn
http://qNiNGEUs.LqLjj.cn
http://QU4D8QrN.LqLjj.cn
http://D8Zrvxa5.LqLjj.cn
http://oO7vJRu1.LqLjj.cn
http://nRWU71hc.LqLjj.cn
http://lOZ1TQWv.LqLjj.cn
http://UxMhXXUx.LqLjj.cn
http://JAvZvIbW.LqLjj.cn
http://rMT4o1tO.LqLjj.cn
http://aIDpQ2jM.LqLjj.cn
http://r9chxNMS.LqLjj.cn
http://iA8sQGlz.LqLjj.cn
http://pyGaueTM.LqLjj.cn
http://32OQ7NFl.LqLjj.cn
http://kieIgg8E.LqLjj.cn
http://2z5Xsq9c.LqLjj.cn
http://www.dtcms.com/a/372771.html

相关文章:

  • B.30.10.05-JVM电商实战应用
  • vulhub fastjson 1.2.24 反序列化导致任意命令执行漏洞
  • [特殊字符] 跨端视频通话实战:腾讯云 TRTC + IM(React Native Web)
  • 【重学 MySQL】九十八、MySQL用户管理全指南:创建、修改、删除
  • 2025时序数据库选型,以IoTDB为主从架构基因到AI赋能来解析
  • 如何用表单快速构建一个用户反馈系统?
  • 2020/12 JLPT听力原文 问题四
  • 基于ConvFormer的双条件域自适应方法的故障诊断模型
  • Day 14: RAG检索增强生成核心技术 - 从原理到实战的完整指南 [特殊字符]
  • mysql 回表查询(二次查询,如何检查,如何规避)
  • vue3+ts使用html2canvas,实现页面截图
  • 疾病语音数据集 WAV格式音频
  • 07 下载配置很完善的yum软件源
  • 【PCIe EP 设备入门学习专栏 -- 8.2.2 PCIe EP Controller Register Types 介绍】
  • 排序---冒泡排序(Bubble Sort)
  • C++/QT day8(9.8)
  • 【Linux网络编程】传输层协议-----UDP协议
  • 医疗连续体机器人模块化控制界面设计与Python库应用研究(上)
  • 分享|构建产教融合的一体化人工智能实验室综合解决方案
  • 从固定 px 到响应式:Vue + Vite 项目响应式改造实战,解决前端不适配的问题
  • java面试:了解MVCC么,详细解释一下
  • ChatGPT 协作调优:把 SQL 查询从 5s 优化到 300ms 的全过程
  • 长春高新需要新叙事
  • Python用PSO优化SVM与RBFN在自动驾驶系统仿真、手写数字分类应用研究
  • android studio JNI 环境配置实现 java 调用 c/c++
  • 安卓非原创--基于Android Studio 实现的新闻App
  • Flutter Android Studio开发实用技巧
  • Android Studio适配butterknife遇到的坑
  • 论文精读(五):面向链接预测的知识图谱表示学习方法综述
  • 使用AI工具一句话生成PPT