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…

相关文章
相关标签/搜索