當 Spring Boot同時遇見application.properties 和 application.yaml,會打架嗎?
在不少 Spring Boot 項目中,我們都會看到這樣的場景:src/main/resources/ 下面靜靜躺著兩個文件——application.properties 與 application.yaml。 它們往往來自不同子模塊、不同年代的代碼庫,甚至是不同開發者的習慣延續。
很多人第一次遇到這種情況時都會心里一緊:“這兩個配置文件,會不會互相覆蓋?到底哪個生效?”
如果你也曾擔心加載順序、覆蓋規則、沖突處理, 那么這篇文章會幫你徹底掌握 Spring Boot 的真實行為,讓你的配置可控、可預期、無坑。
前言:兩個配置文件共存,到底會發生什么?
大多數項目只會使用 .properties 或 .yaml 的其中一種,但現實開發經常會因歷史原因混用。 而 Spring Boot 又足夠“包容”,不會阻止你這么做。
真正的問題不是“能不能同時存在”,而是: ——“同時存在時,Spring Boot 會怎么處理?”
如果不了解其中的優先級機制,你可能會遇到以下經典場景:
- 本地調試和生產環境的行為不一致
- 值被“悄悄覆蓋”,日志卻完全沒有提示
- 配置合并后,某些 key 失效卻毫無征兆
- 新人接手項目根本不知道哪份文件才是“最終配置”
因此,理解 Spring Boot 的配置加載機制,不僅是編碼知識,更是工程穩定性的基礎。
Spring Boot 的真實行為:它會加載兩個文件,而且都算數!
在 /src/main/resources/ 目錄下,當 Spring Boot 啟動時,會同時掃描并加載:
application.properties
application.yml
application.yamlSpring Boot 不會偏袒 YAML,也不會因為你使用 properties 就忽略 YAML。
它會把所有文件都加載進來,并最終合并成一個扁平化(flattened)的配置映射。
這意味著:
- 兩種格式可以共存
- key 會合并
- 如果 key 沖突,會出現覆蓋關系
- 最終生效的是“覆蓋后”的那份完整配置
但真正關鍵的問題是:多個文件都定義了同一個 key 時,到底誰覆蓋誰?
覆蓋規則揭曉:不是字母序,不是文件名長度,是“加載順序”!
我們直接看一組覆寫示例:
application.properties
server.port=8080application.yaml
server:
port: 9090你可能會猜測:
- properties 更傳統 → 也許它優先?
- 文件名字母序 properties < yaml → 也許它先?
- YAML 結構更強 → 也許它優先?
都不是。
Spring Boot 的真實加載順序是固定的:
application.propertiesapplication.ymlapplication.yaml
結論:YAML 永遠比 properties 后加載,因此當 key 沖突時——YAML 覆蓋 properties。
這就是為什么最終生效的端口是 9090。
這不是“YAML 優先”,而是“后加載者優先”。
Spring Boot 會合并配置嗎?答案是:會,而且合得很好
來看另一組例子:
application.properties
spring.datasource.url=jdbc:postgresql://localhost/db1application.yaml
spring:
datasource:
username: appuserSpring Boot 并不會二選一。它會將兩份配置合并成:
spring.datasource.url=...
spring.datasource.username=...除非是同一個 key,否則不會覆蓋。
這解釋了為什么一些混用配置的項目仍然能正常跑起來。
實際開發最容易踩的坑
配置更新無效
你改了 application.properties,但應用仍按 YAML 的值運行。 原因是:YAML 在后加載,默默覆蓋了你的更新。
Git merge 造成隱形沖突
兩個分支分別更新不同格式的配置文件,合并時并不會沖突……但運行時卻 YAML 覆蓋 properties。
生產環境殘留舊 YAML 文件
本地沒有 YAML → properties 生效 服務器殘留 YAML → 覆蓋掉你的所有結果
這類問題尤其難排查。
所有 profile 也遵循同樣規則
Spring Boot 加載 profile 的順序也保持一致:
基礎配置:
application.propertiesapplication.ymlapplication.yaml
Profile 配置:
application-dev.propertiesapplication-dev.ymlapplication-dev.yaml
依然是 YAML > properties。
所以不要幻想 profile 會“例外處理”,它不會。
最佳實踐:只用一種格式,不混用
混用格式帶來的問題不是技術問題,而是工程可維護性問題。
如果你的項目符合以下任意條件:
- 有新人加入
- 有多個開發支線并行
- 配置數量龐大
- 有 CI/CD 流程
- 有多環境部署
那么混用格式都是定時炸彈。
建議: 確立團隊規則,只用一種—— YAML 或 properties。 不要兩者同時維護。
如果你現在項目里已經混用了,怎么辦?
做一次全局搜索,檢查是否有重復 key:
server.port
spring.datasource.*
logging.*
management.*
自定義前綴(如 com.icoderoad.*)把所有重復 key 合并到同一份文件。 然后刪除另一份配置文件。 你會在未來節省大量的溝通與 debug 成本。
示例:在代碼中讀取配置(包名前綴:com.icoderoad)
package com.icoderoad.config;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
@Component
public class ServerConfig {
@Value("${server.port}")
private Integer port;
public Integer getPort() {
return port;
}
}結論:了解規則,你的配置就不會“神秘失效”
Spring Boot 的多文件格式支持,為靈活性而生,但也容易造成隱蔽沖突。 其核心機制很簡單:
- Spring Boot 會加載所有格式
- 非沖突配置會合并
- 同名 key 按加載順序覆蓋
- YAML 在 properties 之后加載
- profile 文件也遵循同樣規則
掌握這些規則后,你的配置將——可預期、可追蹤、可維護。 不再被“為什么生效的不是我寫的值?”困擾,也不再需要為了一個端口號 debug 半天。
工程穩定性的關鍵并不是避免新技術,而是確保團隊配置規則始終一致、明確、可控。


























