Spring Boot 2.4 配置文件加載機制大變化

Spring Boot 2.4.0.M2 剛剛發佈,它對 application.propertiesapplication.yml 文件的加載方式進行重構。若是應用程序僅使用單個 application.propertiesapplication.yml 做爲配置文件,那麼可能感覺不到任何區別。可是若是您的應用程序使用更復雜的配置(例如,Spring Cloud 配置中心等),則須要來了解更改的內容以及緣由。html

爲何要進行這些更改

隨着最新版本 Spring Boot 發佈,Spring 一直在努力提高對 Kubernetes 的原生支持。在 Spring Boot 2.3 中,官方想增長 Kubernetes Volume 的配置支持可是未能實現。java

Volume 配置掛載是 Kubernetes 的一項經常使用功能,其中 ConfigMap 指令用於直接在文件系統上顯示配置。您能夠裝載包含多個鍵和值合併的完整 YAML 文件,也可使用更簡單的目錄樹格式,其中文件名是鍵,文件內容是值。git

但願同時提供二者的支持,而且可以兼容咱們現有的 application.propertiesapplication.yml 。爲此須要修改 ConfigFileApplicationListener 類。github

ConfigFileApplicationListener 問題

在 Spring Boot 中配置文件加載類 ConfigFileApplicationListener 屬於比較核心的底層代碼,每次維護都是很是的困難。並非由於代碼編寫錯誤或者缺乏相關單元測試,而是在添加新功能時,很難解決以前存在的問題。spring

即:數據庫

  • 配置文件很是靈活,能夠在當前文件啓用其餘配置文件。
  • 文檔加載順序不固定。

如下面的例子來講:markdown

security.user.password: usera
---
spring.profiles: local
security.user.password: userb
runlocal: true
---
spring.profiles: !dev
spring.profiles.include: local
security.user.password: userc
複製代碼

在這裏,咱們有一個 多文檔 YAML文件(一個文件由三個邏輯文檔組成,由 --- 分隔)。app

若是使用 --spring.profile.actives=prod 運行,那麼 security.user.password 的值是什麼?是否設置 runlocal 屬性?中間部分文檔是否包括在內,由於配置文件在處理時沒有激活?spring-boot

咱們常常會遇到關於這個文件處理邏輯的問題,可是每當試圖修復它們時,最後帶來各類各樣的負面問題。oop

所以,在 Spring boot 2.4 中對 Properties 和 YAML 文件的加載方式進行兩個重大更改:

  1. 文檔將按定義的順序加載。
  2. profiles 激活開關不能被配置在特定環境中。

文檔排序

從 Spring Boot 2.4 開始,加載 Properties 和 YAML 文件時候會遵循, 在文檔中聲明排序靠前的屬性將被靠後的屬性覆蓋

這點與 .properties 的排序規則相同。咱們能夠想想,每次將一個 Value 放入 Map ,具備相同 key 的新值放入時,將替換已經存在的 Value。

同理對 Multi-document 的 YAML 文件,較低的排序也將被較高的覆蓋:

test: "value"
---
test: "overridden-value"
複製代碼

Properties 文件支持多文檔屬性

在 Spring Boot 2.4 中, Properties 支持相似 YAML 多文檔功能。多文檔屬性文件使用註釋( # )後跟三個(---)破折號來分隔文檔( 選擇使用註釋,以使現有的 IDE 正常支持 )。

例如,上面的 YAML 等效的 properties 爲:

test=value
#---
test=overridden-value
複製代碼

特定環境激活配置

上述示例實際上沒有任何意義,在咱們開發過程當中更爲常見是聲明某個屬性僅在特定環境生效激活。

在 Spring Boot 2.3 中能夠配置 spring.profiles 來實現。但在 Spring Boot 2.4 中 屬性更改spring.config.activate.on-profile

例如,咱們想要 test 屬性僅僅在 dev Profile 激活時覆蓋它,則可使用如下配置:

test=value
#---
spring.config.activate.on-profile=dev
test=overridden-value
複製代碼

Profile Activation

使用 spring.profiles.active 屬性在 application.propertiesapplication.yaml 文件的 根配置文件 來激 相關環境文件。

例如,下面這樣:

test=value
spring.profiles.active=local
#---
spring.config.activate.on-profile=dev
test=overridden value
複製代碼

不容許的是將 spring.profiles.active 屬性與 spring.config.activate.on-profile 一塊兒使用。例如,如下文件將引起異常:

test=value
#---
spring.config.activate.on-profile=dev
spring.profiles.active=local # will fail
test=overridden value
複製代碼

經過這一新限制能使 application.propertiesapplication.yml 文件更加容易理解。使得 Spring Boot 自己更易於管理和維護。

Profile Groups

Profile Groups 是 Spring Boot 2.4 中的一項新功能,可以讓您將單個配置文件擴展爲多個子配置文件。例如,假設有一組複雜的 @Configuration 類,可使用 @Profile 註釋有條件地啓用它們。使用 @Profile("proddb") 開啓數據庫配置,使用 @Profile("prodmq") 開啓消息配置等等。

使用多個配置文件可使咱們的代碼更易於理解,可是對於部署而言並非理想的選擇。若用戶須要同時激活 proddbprodmqprodmetrics 等。那麼 Profile Groups 可以讓您作到這一點。

您能夠在 application.propertiesapplication.yml 文件中定義 spring.profiles.group,那麼開啓 prod 則就至關於激活了此組的所有環境 。例如:

spring.profiles.group.prod=proddb,prodmq,prodmetrics
複製代碼

Importing 擴展 Configuration

如今,咱們已經解決了配置文件處理的基本問題,咱們終於可以考慮咱們想要提供的新功能。咱們使用 Spring Boot 2.4 提供的主要功能是支持導入其餘配置。

對於早期版本的 Spring Boot,很難在 application.propertiesapplication.yml 以外導入其餘 propertiesyaml 文件。可使用 spring.config.additional-location 屬性但它能夠處理的文件類型很是有限。

在 Spring Boot 2.4 能夠直接在 application.propertiesapplication.yml 文件中使用新的 spring.config.import 屬性。例如但願導入一個 "忽略的 git" 的 developer.properties 文件,以便團隊中的任何開發人員均可以快速更改屬性:

application.name=myapp
spring.config.import=developer.properties
複製代碼

甚至能夠將 spring.config.importspring.config.activate.on-profile 結合起來使用。例如,這裏 prod.properties 僅在 prod 配置文件處於激活狀態時加載:

spring.config.activate.on-profile=prod
spring.config.import=prod.properties
複製代碼

Import 能夠被視爲在聲明它們的文檔下方插入的其餘文檔。它們 遵循與常規多文檔文件相同的自上而下的順序:導入僅被導入一次,不管聲明瞭多少次。

volume 掛載配置

導入定義使用與 URL 同樣語法做爲其值。若是您的位置沒有前綴,則它被視爲常規文件或文件夾。可是,若是您使用 configtree: 前綴,則告訴 Spring Boot,您將指望在該位置使用 Kubernetes volume 裝載的配置樹。

例如,您能夠在 application.properties 配置:

spring.config.import=configtree:/etc/config
複製代碼

若是您有如下裝載的內容:

etc/
 +- config/
     +- my/
     |  +- application
     +- test
複製代碼

將在 Spring Environment 中擁有 my.applicationtest 屬性。 my.application 的值是 /etc/config/my/application 的內容, test 的值是 /etc/config/test 的內容。

根據雲平臺類型激活

若是隻但願 Volume 掛載的配置(或該內容的任何屬性)在特 定的雲平臺上 處於激活狀態,可使用 spring.config.activate.on-cloud-platform 屬性。它的工做方式與 spring.config.activate.on-profile 相似,但它使用 CloudPlatform 的值,而不是配置文件名稱。

若是咱們想要在部署到 Kubernetes 時啓用上述配置樹,咱們能夠執行如下操做:

spring.config.activate.on-cloud-platform=kubernetes
spring.config.import=configtree:/etc/config
複製代碼

支持其餘位置

spring.config.import 屬性中指定的位置字符串是徹底可插拔的,能夠經過編寫幾個自定義類來擴展,第三方庫將對自定義位置提供支持。例如,你能想到的第三方 jar 文件,例如 archaius://…vault://…zookeeper://…

若是您有興趣添加其餘位置支持,請查看 org.springframework.boot.context.configConfigDataLocationResolverConfigDataLoader 的 javadoc。

版本回滾

正如上文所描述的,Spring Boot 針對配置文件的功能變動是很是大的。考慮到低版本的兼容性

能夠設置 spring.config.use-legacy-processing=true 屬性便可,恢復到以前版本的文件處理機制。

若是發現關於此處的問題,則須要切換到舊版處理,請 在 GitHub 上提出問題,官方將嘗試解決該問題。

總結

官方但願新的配置數據處理更加好用,而且不會引發太多升級麻煩。若是您想了解更多有關它們的信息,能夠查閱更新的 參考文檔

歡迎關注我,後續會經過代碼來詳細說明此處變動。

翻譯: 冷冷、如夢技術

原文連接:spring.io/blog/2020/0…

相關文章
相關標籤/搜索