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


Spring Boot 2.4.0.M2 剛剛發布,它對 application.propertiesapplication.yml 文件的加載方式進行重構。如果應用程序僅使用單個 application.propertiesapplication.yml 作為配置文件,那么可能感受不到任何區別。但是如果您的應用程序使用更復雜的配置(例如,Spring Cloud 配置中心等),則需要來了解更改的內容以及原因。

為什么要進行這些更改

隨着最新版本 Spring Boot 發布,Spring 一直在努力提升對 Kubernetes 的原生支持。在 Spring Boot 2.3 中,官方增加 Kubernetes Volume 的配置支持,但是未能實現。

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

希望同時提供兩者的支持,並且能夠兼容我們現有的 application.propertiesapplication.yml 。為此需要修改 ConfigFileApplicationListener 類。

ConfigFileApplicationListener 問題

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

即:

  • 配置文件非常靈活,可以在當前文件啟用其他配置文件。
  • 文檔加載順序不固定。

以下面的例子來說:

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文件(一個文件由三個邏輯文檔組成,由 --- 分隔)。

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

我們經常會遇到關於這個文件處理邏輯的問題,但是每當試圖修復它們時,最后帶來各種各樣的負面問題。

因此,在 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 上提出問題,官方將嘗試解決該問題。

總結

官方希望新的配置數據處理更加好用,並且不會引起太多升級麻煩。如果您想了解更多有關它們的信息,可以查閱更新的 參考文檔

歡迎關注我,后續會通過代碼來詳細說明此處變更。

翻譯: 冷冷、如夢技術

原文鏈接:https://spring.io/blog/2020/08/14/config-file-processing-in-spring-boot-2-4

項目推薦: Spring Cloud 、Spring Security OAuth2的RBAC權限管理系統 歡迎關注


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM