此版本仍在开发中,尚未被视为稳定版本。对于最新的稳定版本,请使用 Spring Boot 3.4.0spring-doc.cn

外部化配置

Spring Boot 允许您外部化配置,以便您可以在不同环境中使用相同的应用程序代码。 您可以使用各种外部配置源,包括 Java 属性文件、YAML 文件、环境变量和命令行参数。spring-doc.cn

属性值可以通过使用 @Value 注解直接注入到 bean 中,通过 Spring 的 Environment 抽象访问,或者通过 @ConfigurationProperties 绑定到结构化对象spring-doc.cn

Spring Boot 使用非常特殊的PropertySource顺序,该顺序旨在允许合理地覆盖值。 后面的属性源可以覆盖前面的属性源中定义的值。 按以下顺序考虑源:spring-doc.cn

  1. 默认属性(通过设置 SpringApplication.setDefaultProperties(Map) 指定)。spring-doc.cn

  2. @PropertySource @Configuration 类上的注释。 请注意,在刷新应用程序上下文之前,此类属性源不会添加到 Environment 中。 现在配置某些属性(例如,在刷新开始之前读取的 and)为时已晚。logging.*spring.main.*spring-doc.cn

  3. 配置数据(例如文件)。application.propertiesspring-doc.cn

  4. 仅在 中具有属性的 RandomValuePropertySourcerandom.*spring-doc.cn

  5. OS 环境变量。spring-doc.cn

  6. Java 系统属性 ()。System.getProperties()spring-doc.cn

  7. JNDI 属性来自 .java:comp/envspring-doc.cn

  8. ServletContext init 参数。spring-doc.cn

  9. ServletConfig 初始化参数。spring-doc.cn

  10. 属性(嵌入在环境变量或系统属性中的内联 JSON)。SPRING_APPLICATION_JSONspring-doc.cn

  11. 命令行参数。spring-doc.cn

  12. properties属性。 可用于 @SpringBootTest 和测试注释,用于测试应用程序的特定切片spring-doc.cn

  13. @DynamicPropertySource Comments。spring-doc.cn

  14. @TestPropertySource 测试中的注释。spring-doc.cn

  15. devtools 处于活动状态时目录中的 devtools 全局设置属性$HOME/.config/spring-bootspring-doc.cn

配置数据文件按以下顺序考虑:spring-doc.cn

  1. 打包在 jar 中的应用程序属性(和 YAML 变体)。application.propertiesspring-doc.cn

  2. 打包在 jar 中(和 YAML 变体)的特定于配置文件的应用程序属性application-{profile}.propertiesspring-doc.cn

  3. 打包的 jar(和 YAML 变体)之外的应用程序属性application.propertiesspring-doc.cn

  4. 打包的 jar(和 YAML 变体)之外特定于配置文件的应用程序属性application-{profile}.propertiesspring-doc.cn

建议整个应用程序坚持使用一种格式。 如果在同一位置有 和 YAML 格式的配置文件,则优先。.properties.properties
如果使用环境变量而不是系统属性,则大多数操作系统不允许使用句点分隔的键名称,但您可以改用下划线(例如,而不是 )。 有关详细信息,请参阅从环境变量绑定SPRING_CONFIG_NAMEspring.config.name
如果应用程序在 servlet 容器或应用程序服务器中运行,则可以使用 JNDI 属性 (in) 或 servlet 上下文初始化参数来代替环境变量或系统属性。java:comp/env

为了提供具体示例,假设您开发了一个使用属性的 @Component,如以下示例所示:namespring-doc.cn

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

@Component
public class MyBean {

	@Value("${name}")
	private String name;

	// ...

}
import org.springframework.beans.factory.annotation.Value
import org.springframework.stereotype.Component

@Component
class MyBean {

	@Value("\${name}")
	private val name: String? = null

	// ...

}

在应用程序类路径上(例如,在 jar 中),您可以有一个文件,该文件为 . 在新环境中运行时,可以在 jar 外部提供一个文件,该文件会覆盖 . 对于一次性测试,您可以使用特定的命令行开关(例如)。application.propertiesnameapplication.propertiesnamejava -jar app.jar --name="Spring"spring-doc.cn

和 endpoints 可用于确定属性具有特定值的原因。 您可以使用这两个终端节点来诊断意外的属性值。 有关详细信息,请参阅 生产就绪功能 部分。envconfigprops

访问命令行属性

默认情况下,SpringApplication将任何命令行选项参数(即以 、 开头的参数,例如)转换为a并将它们添加到 Spring Environment。 如前所述,命令行属性始终优先于基于文件的属性源。----server.port=9000propertyspring-doc.cn

如果不希望将命令行属性添加到环境中,则可以使用 来禁用它们。SpringApplication.setAddCommandLineProperties(false)spring-doc.cn

JSON 应用程序属性

环境变量和系统属性通常具有限制,这意味着无法使用某些属性名称。 为了帮助解决这个问题, Spring Boot 允许您将一个属性块编码为单个 JSON 结构。spring-doc.cn

当您的应用程序启动时,将解析 any 或 properties 并将其添加到 Environment 中。spring.application.jsonSPRING_APPLICATION_JSONspring-doc.cn

例如,可以在 UN*X shell 的命令行中将该属性作为环境变量提供:SPRING_APPLICATION_JSONspring-doc.cn

$ SPRING_APPLICATION_JSON='{"my":{"name":"test"}}' java -jar myapp.jar

在前面的示例中,您最终会进入 Spring Environmentmy.name=testspring-doc.cn

相同的 JSON 也可以作为系统属性提供:spring-doc.cn

$ java -Dspring.application.json='{"my":{"name":"test"}}' -jar myapp.jar

或者,您可以使用命令行参数提供 JSON:spring-doc.cn

$ java -jar myapp.jar --spring.application.json='{"my":{"name":"test"}}'

如果要部署到经典 Application Server,则还可以使用名为 的 JNDI 变量。java:comp/env/spring.application.jsonspring-doc.cn

尽管 JSON 中的值将添加到生成的属性源中,但 PropertySourcesPropertyResolver 会将属性视为缺失值。 这意味着 JSON 无法使用值覆盖低阶属性源中的属性。nullnullnull

外部应用程序属性

Spring Boot 将在应用程序启动时自动从以下位置查找并加载文件:application.propertiesapplication.yamlspring-doc.cn

  1. 从 classpathspring-doc.cn

    1. 类路径根spring-doc.cn

    2. classpath 包/configspring-doc.cn

  2. 从当前目录spring-doc.cn

    1. 当前目录spring-doc.cn

    2. 当前目录中的子目录config/spring-doc.cn

    3. 子目录的直接子目录config/spring-doc.cn

该列表按优先级排序(较低项中的值将覆盖较早项的值)。 加载文件中的文档将作为PropertySource实例添加到 Spring Environment中。spring-doc.cn

如果您不喜欢作为配置文件名,则可以通过指定 environment 属性来切换到其他文件名。 例如,要查找 and 文件,您可以按如下方式运行应用程序:applicationspring.config.namemyproject.propertiesmyproject.yamlspring-doc.cn

$ java -jar myproject.jar --spring.config.name=myproject

您还可以使用 environment 属性引用显式位置。 此属性接受要检查的一个或多个位置的逗号分隔列表。spring.config.locationspring-doc.cn

以下示例显示如何指定两个不同的文件:spring-doc.cn

$ java -jar myproject.jar --spring.config.location=\
	optional:classpath:/default.properties,\
	optional:classpath:/override.properties
如果位置是可选的,并且您不介意它们不存在,请使用前缀。optional:
spring.config.name、 和 用于确定必须加载哪些文件。 它们必须定义为环境属性(通常是 OS 环境变量、系统属性或命令行参数)。spring.config.locationspring.config.additional-location

如果包含目录(而不是文件),则它们应以 . 在运行时,它们将附加加载之前生成的名称。 中指定的文件将直接导入。spring.config.location/spring.config.namespring.config.locationspring-doc.cn

目录和文件位置值也都进行了扩展,以检查特定于配置文件的文件。 例如,如果您有 of ,您还会发现加载了相应的文件。spring.config.locationclasspath:myconfig.propertiesclasspath:myconfig-<profile>.properties

在大多数情况下,您添加的每个项目都将引用一个文件或目录。 位置按其定义顺序进行处理,较晚的位置可以覆盖较早的位置的值。spring.config.locationspring-doc.cn

如果你有一个复杂的位置设置,并且你使用特定于配置文件的配置文件,你可能需要提供进一步的提示,以便 Spring Boot 知道应该如何对它们进行分组。 位置组是所有位置都被视为同一级别的位置的集合。 例如,您可能希望对所有 Classpath 位置进行分组,然后对所有外部位置进行分组。 位置组中的项目应以 分隔。 有关更多详细信息,请参阅 Profile Specific Files 部分中的示例。;spring-doc.cn

使用 配置的位置将替换默认位置。 例如,如果配置了值 ,则考虑的完整位置集为:spring.config.locationspring.config.locationoptional:classpath:/custom-config/,optional:file:./custom-config/spring-doc.cn

  1. optional:classpath:custom-config/spring-doc.cn

  2. optional:file:./custom-config/spring-doc.cn

如果您希望添加其他位置而不是替换它们,则可以使用 . 从其他位置加载的属性可以覆盖默认位置中的属性。 例如,如果配置了值 ,则考虑的完整位置集为:spring.config.additional-locationspring.config.additional-locationoptional:classpath:/custom-config/,optional:file:./custom-config/spring-doc.cn

  1. optional:classpath:/;optional:classpath:/config/spring-doc.cn

  2. optional:file:./;optional:file:./config/;optional:file:./config/*/spring-doc.cn

  3. optional:classpath:custom-config/spring-doc.cn

  4. optional:file:./custom-config/spring-doc.cn

此搜索顺序允许您在一个配置文件中指定默认值,然后在另一个配置文件中选择性地覆盖这些值。 您可以在其中一个默认位置 (或您选择的任何其他 basename ) 中为应用程序提供默认值。 然后,可以在运行时使用位于其中一个自定义位置的不同文件覆盖这些默认值。application.propertiesspring.config.namespring-doc.cn

可选位置

默认情况下,当指定的配置数据位置不存在时, Spring Boot 将抛出ConfigDataLocationNotFoundException,并且您的应用程序将无法启动。spring-doc.cn

如果要指定位置,但不介意它并不总是存在,则可以使用前缀。 你可以将此前缀与and属性以及spring.config.import声明一起使用。optional:spring.config.locationspring.config.additional-locationspring-doc.cn

例如,值 of 允许您的应用程序启动,即使文件缺失也是如此。spring.config.importoptional:file:./myconfig.propertiesmyconfig.propertiesspring-doc.cn

如果要忽略所有 ConfigDataLocationNotFoundException 错误并始终继续启动应用程序,则可以使用该属性。 将值设置为 using 或 with a system/environment variable。spring.config.on-not-foundignoreSpringApplication.setDefaultProperties(…​)spring-doc.cn

通配符位置

如果配置文件位置包含最后一个路径段的字符,则将其视为通配符位置。 加载配置时,通配符会展开,以便同时检查直接子目录。 通配符位置在 Kubernetes 等环境中,当有多个 config 属性来源时特别有用。*spring-doc.cn

例如,如果您有一些 Redis 配置和一些 MySQL 配置,您可能希望将这两个配置分开,同时要求这两个配置都存在于一个文件中。 这可能会导致两个单独的文件挂载在不同的位置,例如 和 。 在这种情况下,如果通配符位置为 ,将导致两个文件都被处理。application.propertiesapplication.properties/config/redis/application.properties/config/mysql/application.propertiesconfig/*/spring-doc.cn

默认情况下, Spring Boot 包含在默认搜索位置中。 这意味着将搜索 jar 之外的目录的所有子目录。config/*//configspring-doc.cn

您可以自己将通配符位置与 和 属性一起使用。spring.config.locationspring.config.additional-locationspring-doc.cn

通配符位置必须仅包含一个通配符位置,对于作为目录的搜索位置或作为文件的搜索位置,通配符位置必须以 结尾。 带有通配符的位置根据文件名的绝对路径按字母顺序排序。**/*/<filename>
通配符位置仅适用于外部目录。 不能在某个位置使用通配符。classpath:

配置文件特定

除了属性文件,Spring Boot 还将尝试使用 naming convention 加载特定于配置文件的文件。 例如,如果您的应用程序激活名为 YAML 文件的配置文件并使用 YAML 文件,则 和 都将被考虑。applicationapplication-{profile}prodapplication.yamlapplication-prod.yamlspring-doc.cn

特定于配置文件的属性从与 standard 相同的位置加载,特定于配置文件的文件始终覆盖非特定文件。 如果指定了多个配置文件,则适用 last-wins 策略。 例如,如果配置文件由属性指定,则 中的值可以被 中的值覆盖。application.propertiesprod,livespring.profiles.activeapplication-prod.propertiesapplication-live.propertiesspring-doc.cn

“最后获胜”策略适用于营业地点组级别。 A of 将具有与 .spring.config.locationclasspath:/cfg/,classpath:/ext/classpath:/cfg/;classpath:/ext/spring-doc.cn

例如,继续上面的示例,我们可能有以下文件:prod,livespring-doc.cn

/cfg
  application-live.properties
/ext
  application-live.properties
  application-prod.properties

当我们有 a of 时,我们会先处理所有文件,然后再处理所有文件:spring.config.locationclasspath:/cfg/,classpath:/ext//cfg/extspring-doc.cn

  1. /cfg/application-live.propertiesspring-doc.cn

  2. /ext/application-prod.propertiesspring-doc.cn

  3. /ext/application-live.propertiesspring-doc.cn

当我们有 (带有分隔符) 时,我们会在同一级别处理 and:classpath:/cfg/;classpath:/ext/;/cfg/extspring-doc.cn

  1. /ext/application-prod.propertiesspring-doc.cn

  2. /cfg/application-live.propertiesspring-doc.cn

  3. /ext/application-live.propertiesspring-doc.cn

环境 有一组默认配置文件(默认情况下为 ),如果未设置活动配置文件,则使用这些配置文件。 换句话说,如果未明确激活任何用户档案,则考虑 中的属性。[default]application-defaultspring-doc.cn

属性文件只加载一次。 如果您已经直接导入了特定于配置文件的属性文件,则不会再次导入它。

导入其他数据

应用程序属性可以使用该属性从其他位置导入进一步的配置数据。 导入在被发现时进行处理,并被视为插入到声明导入的导入文档的正下方的附加文档。spring.config.importspring-doc.cn

例如,您的 Classpath 文件中可能包含以下内容:application.propertiesspring-doc.cn

spring.application.name=myapp
spring.config.import=optional:file:./dev.properties
spring:
  application:
    name: "myapp"
  config:
    import: "optional:file:./dev.properties"

这将触发当前目录中文件的导入(如果存在此类文件)。 导入的值将优先于触发导入的文件。 在上面的示例中,可以重新定义为不同的值。dev.propertiesdev.propertiesdev.propertiesspring.application.namespring-doc.cn

无论声明多少次,导入都只会导入一次。 在 properties/yaml 文件中的单个文档中定义导入的顺序无关紧要。 例如,下面的两个示例产生相同的结果:spring-doc.cn

spring.config.import=my.properties
my.property=value
spring:
  config:
    import: "my.properties"
my:
  property: "value"
my.property=value
spring.config.import=my.properties
my:
  property: "value"
spring:
  config:
    import: "my.properties"

在上述两个示例中,文件中的值将优先于触发其导入的文件。my.propertiesspring-doc.cn

可以在单个键下指定多个位置。 位置将按照定义的顺序进行处理,以后的导入优先。spring.config.importspring-doc.cn

在适当时,还会考虑导入特定于 Profile 的变体。 上面的示例将导入 both 以及 any variants。my.propertiesmy-<profile>.properties

Spring Boot 包含可插拔 API,允许支持各种不同的位置地址。 默认情况下,您可以导入 Java 属性、YAML 和配置树spring-doc.cn

第三方 jar 可以提供对其他技术的支持(不要求文件是本地的)。 例如,您可以想象配置数据来自 Consul、Apache ZooKeeper 或 Netflix Archaius 等外部存储。spring-doc.cn

如果要支持自己的位置,请参阅包中的 ConfigDataLocationResolverConfigDataLoader 类。org.springframework.boot.context.configspring-doc.cn

导入无扩展名文件

某些云平台无法向卷挂载的文件添加文件扩展名。 要导入这些无扩展名文件,你需要给 Spring Boot 一个提示,以便它知道如何加载它们。 您可以通过在方括号中放置扩展提示来执行此操作。spring-doc.cn

例如,假设您有一个希望作为 yaml 导入的文件。 您可以使用以下方法将其导入:/etc/config/myconfigapplication.propertiesspring-doc.cn

spring.config.import=file:/etc/config/myconfig[.yaml]
spring:
  config:
    import: "file:/etc/config/myconfig[.yaml]"

使用配置树

在云平台(如 Kubernetes)上运行应用程序时,您通常需要读取平台提供的配置值。 将环境变量用于此类目的并不少见,但这可能有缺点,尤其是在值应该保密的情况下。spring-doc.cn

作为环境变量的替代方案,许多云平台现在允许您将配置映射到挂载的数据卷。 例如,Kubernetes 可以同时对 ConfigMapSecret 进行卷挂载。spring-doc.cn

可以使用两种常见的卷挂载模式:spring-doc.cn

  1. 单个文件包含一组完整的属性(通常写为 YAML)。spring-doc.cn

  2. 多个文件被写入目录树,文件名成为 'key',内容成为 'value'。spring-doc.cn

对于第一种情况,您可以如上所述直接使用 YAML 或 Properties 文件导入。 对于第二种情况,你需要使用前缀,以便 Spring Boot 知道它需要将所有文件作为属性公开。spring.config.importconfigtree:spring-doc.cn

例如,假设 Kubernetes 挂载了以下卷:spring-doc.cn

etc/
  config/
    myapp/
      username
      password

文件的内容将是 config 值,而 的内容将是 secret。usernamepasswordspring-doc.cn

要导入这些属性,您可以将以下内容添加到您的 or 文件中:application.propertiesapplication.yamlspring-doc.cn

spring.config.import=optional:configtree:/etc/config/
spring:
  config:
    import: "optional:configtree:/etc/config/"

然后,你可以像往常一样从 Environment 访问或注入 and 属性。myapp.usernamemyapp.passwordspring-doc.cn

配置树下的文件夹和文件的名称构成属性名称。 在上面的示例中,要访问属性 as 和 ,您可以设置为 。usernamepasswordspring.config.importoptional:configtree:/etc/config/myapp
带有点表示法的文件名也会正确映射。 例如,在上面的示例中,名为 in 的文件将在 Environment 中生成一个属性。myapp.username/etc/configmyapp.username
配置树值可以绑定到字符串 String 和 types,具体取决于预期的内容。byte[]

如果要从同一个父文件夹导入多个配置树,则可以使用通配符快捷方式。 任何以 结尾的位置都会将所有直接子项作为配置树导入。 与非通配符导入一样,每个配置树下的文件夹和文件的名称构成属性名称。configtree:/*/spring-doc.cn

例如,给定以下卷:spring-doc.cn

etc/
  config/
    dbconfig/
      db/
        username
        password
    mqconfig/
      mq/
        username
        password

您可以用作导入位置:configtree:/etc/config/*/spring-doc.cn

spring.config.import=optional:configtree:/etc/config/*/
spring:
  config:
    import: "optional:configtree:/etc/config/*/"

这将添加 、 和 属性。db.usernamedb.passwordmq.usernamemq.passwordspring-doc.cn

使用通配符加载的目录按字母顺序排序。 如果您需要不同的顺序,则应将每个位置列为单独的导入

配置树还可用于 Docker 密钥。 当 Docker Swarm 服务被授予对 secret 的访问权限时,secret 将被挂载到容器中。 例如,如果名为 的密钥挂载在 location ,则可以使用以下内容对 Spring 环境可用:db.password/run/secrets/db.passwordspring-doc.cn

spring.config.import=optional:configtree:/run/secrets/
spring:
  config:
    import: "optional:configtree:/run/secrets/"

属性占位符

和 中的值在使用时通过现有 Environment 进行筛选,因此您可以参考以前定义的值(例如,来自 System properties 或 environment variables)。 标准 property-placeholder 语法可以在值中的任何位置使用。 属性占位符还可以使用 a 将默认值与属性名称分开,例如 。application.propertiesapplication.yaml${name}:${name:default}spring-doc.cn

以下示例显示了带和不带默认值的占位符的用法:spring-doc.cn

app.name=MyApp
app.description=${app.name} is a Spring Boot application written by ${username:Unknown}
app:
  name: "MyApp"
  description: "${app.name} is a Spring Boot application written by ${username:Unknown}"

假设该属性尚未在其他位置设置,则其值为 .usernameapp.descriptionMyApp is a Spring Boot application written by Unknownspring-doc.cn

您应该始终使用其规范形式(kebab-case 仅使用小写字母)在占位符中引用属性名称。 这将允许 Spring Boot 使用与松散绑定@ConfigurationProperties时相同的逻辑。spring-doc.cn

例如,将从文件以及系统环境中选取 和 form。 如果你改用,则不会被考虑。${demo.item-price}demo.item-pricedemo.itemPriceapplication.propertiesDEMO_ITEMPRICE${demo.itemPrice}demo.item-priceDEMO_ITEMPRICEspring-doc.cn

您还可以使用此技术创建现有 Spring Boot 属性的“短”变体。 有关详细信息,请参阅 “How-to Guides” 中的 Use 'short' Command Line Arguments 部分。

使用多文档文件

Spring Boot 允许您将单个物理文件拆分为多个 logical 文档,每个 logical 文档都是独立添加的。 文档按从上到下的顺序处理。 后面的文档可以覆盖前面文档中定义的属性。spring-doc.cn

对于文件,使用标准的 YAML 多文档语法。 三个连续的连字符表示一个文档的结尾和下一个文档的开头。application.yamlspring-doc.cn

例如,以下文件有两个逻辑文档:spring-doc.cn

spring:
  application:
    name: "MyApp"
---
spring:
  application:
    name: "MyCloudApp"
  config:
    activate:
      on-cloud-platform: "kubernetes"

对于文件,使用 special 或 comment 来标记文档拆分:application.properties#---!---spring-doc.cn

spring.application.name=MyApp
#---
spring.application.name=MyCloudApp
spring.config.activate.on-cloud-platform=kubernetes
属性文件分隔符不得有任何前导空格,并且必须恰好包含三个连字符。 紧接在分隔符之前和之后的行不能是相同的注释前缀。
多文档属性文件通常与激活属性(如 . 有关详细信息,请参阅下一节spring.config.activate.on-profile
无法使用 @PropertySource@TestPropertySource 注释加载多文档属性文件。

激活属性

有时,仅在满足某些条件时激活一组给定的属性很有用。 例如,您可能具有仅在特定配置文件处于活动状态时才相关的属性。spring-doc.cn

您可以使用 有条件地激活属性文档。spring.config.activate.*spring-doc.cn

可以使用以下激活属性:spring-doc.cn

表 1.激活属性
财产 注意

on-profilespring-doc.cn

必须匹配的配置文件表达式,文档才能处于活动状态。spring-doc.cn

on-cloud-platformspring-doc.cn

必须检测到的 CloudPlatform 才能使文档处于活动状态。spring-doc.cn

例如,以下指定第二个文档仅在 Kubernetes 上运行时处于活动状态,并且仅当 “prod” 或 “staging” 配置文件处于活动状态时:spring-doc.cn

myprop=always-set
#---
spring.config.activate.on-cloud-platform=kubernetes
spring.config.activate.on-profile=prod | staging
myotherprop=sometimes-set
myprop:
  "always-set"
---
spring:
  config:
    activate:
      on-cloud-platform: "kubernetes"
      on-profile: "prod | staging"
myotherprop: "sometimes-set"

加密属性

Spring Boot 不提供对加密属性值的任何内置支持,但是,它确实提供了修改 Spring Environment 中包含的值所需的钩子点。 EnvironmentPostProcessor 接口允许您在应用程序启动之前操作 Environment。 有关详细信息,请参见Customize the Environment 或 ApplicationContext Before It Startedspring-doc.cn

如果你需要一种安全的方式来存储凭证和密码,Spring Cloud Vault 项目提供了在 HashiCorp Vault 中存储外部化配置的支持。spring-doc.cn

使用 YAML

YAML 是 JSON 的超集,因此是指定分层配置数据的便捷格式。 每当 Classpath 上有 SnakeYAML 库时,SpringApplication 类就会自动支持 YAML 作为属性的替代方案。spring-doc.cn

如果您使用 starters,则 SnakeYAML 会自动由 .spring-boot-starter

将 YAML 映射到属性

YAML 文档需要从其分层格式转换为可与 Spring Environment 一起使用的平面结构。 例如,请考虑以下 YAML 文档:spring-doc.cn

environments:
  dev:
    url: "https://dev.example.com"
    name: "Developer Setup"
  prod:
    url: "https://another.example.com"
    name: "My Cool App"

为了从 Environment 访问这些属性,它们将被扁平化,如下所示:spring-doc.cn

environments.dev.url=https://dev.example.com
environments.dev.name=Developer Setup
environments.prod.url=https://another.example.com
environments.prod.name=My Cool App

同样,YAML 列表也需要扁平化。 它们表示为带有取消引用器的属性键。 例如,请考虑以下 YAML:[index]spring-doc.cn

 my:
  servers:
  - "dev.example.com"
  - "another.example.com"

前面的示例将转换为以下属性:spring-doc.cn

my.servers[0]=dev.example.com
my.servers[1]=another.example.com
使用该表示法的属性可以使用 Spring Boot 的 Binder 类绑定到 Java ListSet 对象。 有关更多详细信息,请参阅下面的类型安全配置属性部分。[index]
无法使用 @PropertySource@TestPropertySource 注释加载 YAML 文件。 因此,如果需要以这种方式加载值,则需要使用属性文件。

直接加载 YAML

Spring Framework 提供了两个方便的类,可用于加载 YAML 文档。 YamlPropertiesFactoryBean 将 YAML 加载为 Properties,而 YamlMapFactoryBean 将 YAML 加载为 Mapspring-doc.cn

如果要将 YAML 加载为 Spring PropertySource,也可以使用 YamlPropertySourceLoader 类。spring-doc.cn

配置随机值

RandomValuePropertySource 可用于注入随机值(例如,注入 Secret 或测试用例)。 它可以生成整数、长整型、uuid 或字符串,如以下示例所示:spring-doc.cn

my.secret=${random.value}
my.number=${random.int}
my.bignumber=${random.long}
my.uuid=${random.uuid}
my.number-less-than-ten=${random.int(10)}
my.number-in-range=${random.int[1024,65536]}
my:
  secret: "${random.value}"
  number: "${random.int}"
  bignumber: "${random.long}"
  uuid: "${random.uuid}"
  number-less-than-ten: "${random.int(10)}"
  number-in-range: "${random.int[1024,65536]}"

语法是其中 s 是任何字符 和 整数。 如果提供,则为最小值和最大值(不包括)。random.int*OPEN value (,max) CLOSEOPEN,CLOSEvalue,maxmaxvaluemaxspring-doc.cn

配置系统环境属性

Spring Boot 支持为环境属性设置前缀。 如果系统环境由具有不同配置要求的多个 Spring Boot 应用程序共享,这将非常有用。 可以直接在 SpringApplication 上设置系统环境属性的前缀。spring-doc.cn

例如,如果将前缀设置为 ,则诸如 这样的属性也将像在系统环境中一样进行解析。inputremote.timeoutinput.remote.timeoutspring-doc.cn

类型安全的配置属性

使用 annotation 注入配置属性有时会很麻烦,尤其是在您使用多个属性或数据本质上是分层的时。 Spring Boot 提供了一种使用属性的替代方法,该方法允许强类型 bean 管理和验证应用程序的配置。@Value("${property}")spring-doc.cn

另请参阅 @Value 和 type-safe 配置属性之间的差异

JavaBean 属性绑定

可以绑定声明标准 JavaBean 属性的 Bean,如下例所示:spring-doc.cn

import java.net.InetAddress;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import org.springframework.boot.context.properties.ConfigurationProperties;

@ConfigurationProperties("my.service")
public class MyProperties {

	private boolean enabled;

	private InetAddress remoteAddress;

	private final Security security = new Security();

	// getters / setters...

	public boolean isEnabled() {
		return this.enabled;
	}

	public void setEnabled(boolean enabled) {
		this.enabled = enabled;
	}

	public InetAddress getRemoteAddress() {
		return this.remoteAddress;
	}

	public void setRemoteAddress(InetAddress remoteAddress) {
		this.remoteAddress = remoteAddress;
	}

	public Security getSecurity() {
		return this.security;
	}

	public static class Security {

		private String username;

		private String password;

		private List<String> roles = new ArrayList<>(Collections.singleton("USER"));

		// getters / setters...

		public String getUsername() {
			return this.username;
		}

		public void setUsername(String username) {
			this.username = username;
		}

		public String getPassword() {
			return this.password;
		}

		public void setPassword(String password) {
			this.password = password;
		}

		public List<String> getRoles() {
			return this.roles;
		}

		public void setRoles(List<String> roles) {
			this.roles = roles;
		}

	}

}
import org.springframework.boot.context.properties.ConfigurationProperties
import java.net.InetAddress

@ConfigurationProperties("my.service")
class MyProperties {

	var isEnabled = false

	var remoteAddress: InetAddress? = null

	val security = Security()

	class Security {

		var username: String? = null

		var password: String? = null

		var roles: List<String> = ArrayList(setOf("USER"))

	}

}

前面的 POJO 定义了以下属性:spring-doc.cn

  • my.service.enabled,默认值为falsespring-doc.cn

  • my.service.remote-address,其类型可以从 String 强制转换。spring-doc.cn

  • my.service.security.username,其中包含一个嵌套的 “security” 对象,其名称由属性名称确定。 具体而言,该类型根本不使用,可能是 SecurityPropertiesspring-doc.cn

  • my.service.security.password.spring-doc.cn

  • my.service.security.roles,其中包含默认为 .USERspring-doc.cn

映射到 Spring Boot 中可用的@ConfigurationProperties类的属性(通过属性文件、YAML 文件、环境变量和其他机制进行配置)是公共 API,但类本身的访问器(getter/setter)并不意味着直接使用。

这种安排依赖于默认的空构造函数,并且 getter 和 setter 通常是强制性的,因为绑定是通过标准 Java Beans 属性描述符进行的,就像在 Spring MVC 中一样。 在以下情况下,可以省略 setter:spring-doc.cn

  • 只要 Map 被初始化,就需要一个 getter,但不一定是一个 setter,因为它们可以被 binders 改变。spring-doc.cn

  • 可以通过索引(通常使用 YAML)或使用单个逗号分隔值(properties)来访问集合和数组。 在后一种情况下,setter 是必需的。 我们建议始终为此类类型添加 setter。 如果初始化集合,请确保它不是不可变的(如前面的示例所示)。spring-doc.cn

  • 如果初始化了嵌套的 POJO 属性(如前面示例中的字段),则不需要 setter。 如果希望 Binders 使用其默认构造函数动态创建实例,则需要 setter。Securityspring-doc.cn

有些人使用 Project Lombok 自动添加 getter 和 setter。 确保 Lombok 不会为此类类型生成任何特定的构造函数,因为容器会自动使用它来实例化对象。spring-doc.cn

最后,仅考虑标准 Java Bean 属性,并且不支持对静态属性进行绑定。spring-doc.cn

构造函数绑定

上一节中的示例可以以不可变的方式重写,如以下示例所示:spring-doc.cn

import java.net.InetAddress;
import java.util.List;

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.bind.DefaultValue;

@ConfigurationProperties("my.service")
public class MyProperties {

	// fields...

	private final boolean enabled;

	private final InetAddress remoteAddress;

	private final Security security;


	public MyProperties(boolean enabled, InetAddress remoteAddress, Security security) {
		this.enabled = enabled;
		this.remoteAddress = remoteAddress;
		this.security = security;
	}

	// getters...

	public boolean isEnabled() {
		return this.enabled;
	}

	public InetAddress getRemoteAddress() {
		return this.remoteAddress;
	}

	public Security getSecurity() {
		return this.security;
	}

	public static class Security {

		// fields...

		private final String username;

		private final String password;

		private final List<String> roles;


		public Security(String username, String password, @DefaultValue("USER") List<String> roles) {
			this.username = username;
			this.password = password;
			this.roles = roles;
		}

		// getters...

		public String getUsername() {
			return this.username;
		}

		public String getPassword() {
			return this.password;
		}

		public List<String> getRoles() {
			return this.roles;
		}

	}

}
import org.springframework.boot.context.properties.ConfigurationProperties
import org.springframework.boot.context.properties.bind.DefaultValue
import java.net.InetAddress

@ConfigurationProperties("my.service")
class MyProperties(val enabled: Boolean, val remoteAddress: InetAddress,
		val security: Security) {

	class Security(val username: String, val password: String,
			@param:DefaultValue("USER") val roles: List<String>)

}

在此设置中,存在单个参数化构造函数意味着应使用构造函数绑定。 这意味着 Binder 将找到一个构造函数,其中包含您希望绑定的参数。 如果您的类具有多个构造函数,则可以使用 @ConstructorBinding 注释来指定要用于构造函数绑定的构造函数。 要选择退出具有单个参数化构造函数的类的构造函数绑定,该构造函数必须用 @Autowired 或 made 进行批注。 构造函数绑定可以与记录一起使用。 除非您的记录具有多个构造函数,否则无需使用 @ConstructorBindingprivatespring-doc.cn

构造函数绑定类的嵌套成员(如上例所示)也将通过其构造函数进行绑定。Securityspring-doc.cn

可以使用 @DefaultValue 构造函数参数和记录组件指定默认值。 将应用转换服务以将 Comments 的 String 值强制转换为缺失属性的目标类型。spring-doc.cn

参考前面的示例,如果没有属性绑定到 ,则实例将包含 的值 。 要使其包含非 null 实例,即使没有绑定到任何属性(使用 Kotlin 时,这需要将 和 参数声明为可为 null,因为它们没有默认值),请使用空的 @DefaultValue 注解:SecurityMyPropertiesnullsecuritySecurityusernamepasswordSecurityspring-doc.cn

	public MyProperties(boolean enabled, InetAddress remoteAddress, @DefaultValue Security security) {
		this.enabled = enabled;
		this.remoteAddress = remoteAddress;
		this.security = security;
	}
class MyProperties(val enabled: Boolean, val remoteAddress: InetAddress,
		@DefaultValue val security: Security) {

	class Security(val username: String?, val password: String?,
			@param:DefaultValue("USER") val roles: List<String>)

}
要使用构造函数绑定,必须使用 @EnableConfigurationProperties 或 configuration 属性扫描来启用该类。 不能将构造函数绑定与由常规 Spring 机制创建的 bean(例如,@Component bean、使用 @Bean 方法创建的 bean 或使用 @Import 加载的 bean)
要使用构造函数绑定,必须使用 . 如果您使用 Spring Boot 的 Gradle 插件,或者如果您使用 Maven 和 .-parametersspring-boot-starter-parent
不建议将 Optional@ConfigurationProperties 一起使用,因为它主要用作返回类型。 因此,它不太适合 configuration property injection。 为了与其他类型的属性保持一致,如果声明了 Optional 属性并且该属性没有值,则将绑定一个空的 Optional,而不是空的。null
要在属性名称中使用 reserved 关键字(如 ),请在 constructor 参数上使用 @Name 注释。my.service.import

启用 @ConfigurationProperties 注释类型

Spring Boot 提供了绑定@ConfigurationProperties类型并将其注册为 bean 的基础设施。 您可以逐个类启用配置属性,也可以启用配置属性扫描,其工作方式与组件扫描类似。spring-doc.cn

有时,用 @ConfigurationProperties 注释的类可能不适合扫描,例如,如果您正在开发自己的自动配置或想要有条件地启用它们。 在这些情况下,请使用 @EnableConfigurationProperties 注释指定要处理的类型列表。 这可以在任何 @Configuration 类上完成,如以下示例所示:spring-doc.cn

import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Configuration;

@Configuration(proxyBeanMethods = false)
@EnableConfigurationProperties(SomeProperties.class)
public class MyConfiguration {

}
import org.springframework.boot.context.properties.EnableConfigurationProperties
import org.springframework.context.annotation.Configuration

@Configuration(proxyBeanMethods = false)
@EnableConfigurationProperties(SomeProperties::class)
class MyConfiguration
import org.springframework.boot.context.properties.ConfigurationProperties;

@ConfigurationProperties("some.properties")
public class SomeProperties {

}
import org.springframework.boot.context.properties.ConfigurationProperties

@ConfigurationProperties("some.properties")
class SomeProperties

要使用配置属性扫描,请将 @ConfigurationPropertiesScan 注释添加到您的应用程序中。 通常,它会添加到用 @SpringBootApplication 注释的主应用程序类中但可以添加到任何@Configuration类中。 默认情况下,将从声明 Comments 的类的包中进行扫描。 如果要定义要扫描的特定包,可以按以下示例所示执行此操作:spring-doc.cn

import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.properties.ConfigurationPropertiesScan;

@SpringBootApplication
@ConfigurationPropertiesScan({ "com.example.app", "com.example.another" })
public class MyApplication {

}
import org.springframework.boot.autoconfigure.SpringBootApplication
import org.springframework.boot.context.properties.ConfigurationPropertiesScan

@SpringBootApplication
@ConfigurationPropertiesScan("com.example.app", "com.example.another")
class MyApplication

当使用配置属性扫描或通过 @EnableConfigurationProperties 注册 @ConfigurationProperties Bean 时,该 Bean 具有约定的名称:,其中 是在 @ConfigurationProperties 注释中指定的环境键前缀,并且是 Bean 的标准名称。 如果 Comments 未提供任何前缀,则仅使用 Bean 的完全限定名称。<prefix>-<fqn><prefix><fqn>spring-doc.cn

假设它在包中,则上面示例的 bean 名称为 。com.example.appSomePropertiessome.properties-com.example.app.SomePropertiesspring-doc.cn

我们建议@ConfigurationProperties只处理环境,特别是不要从上下文中注入其他 bean。 对于极端情况,可以使用 setter 注入或框架提供的任何接口(例如,如果您需要访问 Environment,则使用 EnvironmentAware)。 如果您仍希望使用构造函数注入其他 bean,则必须使用 @Component 注释配置属性 bean,并使用基于 JavaBean 的属性绑定。*Awarespring-doc.cn

使用 @ConfigurationProperties 注释的类型

这种配置样式特别适用于SpringApplication外部 YAML 配置,如以下示例所示:spring-doc.cn

my:
  service:
    remote-address: 192.168.1.1
    security:
      username: "admin"
      roles:
      - "USER"
      - "ADMIN"

要使用 @ConfigurationProperties bean,可以采用与任何其他 bean 相同的方式注入它们,如以下示例所示:spring-doc.cn

import org.springframework.stereotype.Service;

@Service
public class MyService {

	private final MyProperties properties;

	public MyService(MyProperties properties) {
		this.properties = properties;
	}

	public void openConnection() {
		Server server = new Server(this.properties.getRemoteAddress());
		server.start();
		// ...
	}

	// ...

}
import org.springframework.stereotype.Service

@Service
class MyService(val properties: MyProperties) {

	fun openConnection() {
		val server = Server(properties.remoteAddress)
		server.start()
		// ...
	}

	// ...

}
使用 @ConfigurationProperties 还可以生成元数据文件,IDE 可以使用这些文件为您自己的键提供自动完成功能。 有关详细信息,请参阅附录

第三方配置

除了使用 @ConfigurationProperties 对类进行注释外,还可以在公共@Bean方法上使用它。 当您希望将属性绑定到不受控制的第三方组件时,这样做可能特别有用。spring-doc.cn

要从 Environment 属性配置 Bean,请将 @ConfigurationProperties 添加到其 Bean 注册中,如以下示例所示:spring-doc.cn

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration(proxyBeanMethods = false)
public class ThirdPartyConfiguration {

	@Bean
	@ConfigurationProperties(prefix = "another")
	public AnotherComponent anotherComponent() {
		return new AnotherComponent();
	}

}
import org.springframework.boot.context.properties.ConfigurationProperties
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration

@Configuration(proxyBeanMethods = false)
class ThirdPartyConfiguration {

	@Bean
	@ConfigurationProperties(prefix = "another")
	fun anotherComponent(): AnotherComponent = AnotherComponent()

}

使用前缀定义的任何 JavaBean 属性都以类似于前面示例的方式映射到该 Bean 上。anotherAnotherComponentSomePropertiesspring-doc.cn

松散绑定

Spring Boot 使用一些宽松的规则将环境属性绑定到 @ConfigurationProperties bean,因此环境属性名称和 bean 属性名称之间不需要完全匹配。 这有用的常见示例包括以短划线分隔的环境属性(例如,binds to )和大写的环境属性(例如,binds to )。context-pathcontextPathPORTportspring-doc.cn

例如,请考虑以下 @ConfigurationProperties 类:spring-doc.cn

import org.springframework.boot.context.properties.ConfigurationProperties;

@ConfigurationProperties(prefix = "my.main-project.person")
public class MyPersonProperties {

	private String firstName;

	public String getFirstName() {
		return this.firstName;
	}

	public void setFirstName(String firstName) {
		this.firstName = firstName;
	}

}
import org.springframework.boot.context.properties.ConfigurationProperties

@ConfigurationProperties(prefix = "my.main-project.person")
class MyPersonProperties {

	var firstName: String? = null

}

使用上述代码,可以使用以下属性名称:spring-doc.cn

表 2.松绑
财产 注意

my.main-project.person.first-namespring-doc.cn

Kebab 大小写,建议在 和 YAML 文件中使用。.propertiesspring-doc.cn

my.main-project.person.firstNamespring-doc.cn

标准 Camel 大小写语法。spring-doc.cn

my.main-project.person.first_namespring-doc.cn

下划线表示法,这是在 和 YAML 文件中使用的替代格式。.propertiesspring-doc.cn

MY_MAINPROJECT_PERSON_FIRSTNAMEspring-doc.cn

大写格式,使用系统环境变量时推荐使用。spring-doc.cn

注释的值必须采用 kebab 大小写(小写并用 分隔,例如 )。prefix-my.main-project.person
表 3.每个属性源的松散绑定规则
Property Source 简单 列表

属性文件spring-doc.cn

驼峰式大小写、kebab 大小写或下划线表示法spring-doc.cn

使用 或 逗号分隔值的标准列表语法[ ]spring-doc.cn

YAML 文件spring-doc.cn

驼峰式大小写、kebab 大小写或下划线表示法spring-doc.cn

标准 YAML 列表语法或逗号分隔值spring-doc.cn

环境变量spring-doc.cn

大写格式,下划线作为分隔符(请参阅从环境变量绑定)。spring-doc.cn

用下划线括起来的数值(请参见从环境变量绑定)spring-doc.cn

系统属性spring-doc.cn

驼峰式大小写、kebab 大小写或下划线表示法spring-doc.cn

使用 或 逗号分隔值的标准列表语法[ ]spring-doc.cn

我们建议尽可能以小写 kebab 格式存储属性,例如 .my.person.first-name=Rod

绑定映射

绑定到 Map 属性时,可能需要使用特殊的方括号表示法,以便保留原始值。 如果键未被 括起来,则任何非字母数字字符或已删除的字符。key[]-.spring-doc.cn

例如,考虑将以下属性绑定到 :Map<String,String>spring-doc.cn

my.map[/key1]=value1
my.map[/key2]=value2
my.map./key3=value3
my:
  map:
    "[/key1]": "value1"
    "[/key2]": "value2"
    "/key3": "value3"
对于 YAML 文件,括号需要用引号括起来,以便正确解析键。

上面的属性将绑定到具有 的 Map,并作为 Map 中的键。 斜杠已被删除,因为它没有被方括号括起来。/key1/key2key3key3spring-doc.cn

当绑定到标量值时,其中包含的键不需要用 . 标量值包括枚举和包中除 Object 之外的所有类型。 Binding to 将保留键中的 the 并返回一个条目为 . 对于任何其他类型,如果包含. 例如,绑定到将返回带有条目的 Map,而将返回带有条目的 Map。.[]java.langa.b=cMap<String, String>.{"a.b"="c"}key.a.b=cMap<String, Object>{"a"={"b"="c"}}[a.b]=c{"a.b"="c"}spring-doc.cn

从环境变量绑定

大多数操作系统对可用于环境变量的名称施加了严格的规则。 例如,Linux shell 变量只能包含字母 ( to 或 to )、数字 ( to ) 或下划线字符 ()。 按照惯例,Unix shell 变量的名称也将采用 UPPERCASE。azAZ09_spring-doc.cn

Spring Boot 的宽松绑定规则尽可能地设计为与这些命名限制兼容。spring-doc.cn

要将 canonical-form 中的属性名称转换为环境变量名称,您可以遵循以下规则:spring-doc.cn

例如,configuration 属性将是名为 .spring.main.log-startup-infoSPRING_MAIN_LOGSTARTUPINFOspring-doc.cn

绑定到对象列表时,也可以使用环境变量。 要绑定到 List,元素编号应在变量名称中用下划线括起来。spring-doc.cn

例如,configuration 属性将使用名为 .my.service[0].otherMY_SERVICE_0_OTHERspring-doc.cn

对从环境变量进行绑定的支持将应用于属性源以及名称以 .systemEnvironment-systemEnvironmentspring-doc.cn

从环境变量绑定映射

当 Spring Boot 将环境变量绑定到属性类时,它会在绑定之前将环境变量名称小写。 大多数情况下,此详细信息并不重要,除非绑定到 Map 属性。spring-doc.cn

Map 中的键始终为小写,如以下示例所示:spring-doc.cn

import java.util.HashMap;
import java.util.Map;

import org.springframework.boot.context.properties.ConfigurationProperties;

@ConfigurationProperties(prefix = "my.props")
public class MyMapsProperties {

	private final Map<String, String> values = new HashMap<>();

	public Map<String, String> getValues() {
		return this.values;
	}

}
import org.springframework.boot.context.properties.ConfigurationProperties

@ConfigurationProperties(prefix = "my.props")
class MyMapsProperties {

	val values: Map<String, String> = HashMap()

}

设置 时,Map 包含一个条目。MY_PROPS_VALUES_KEY=valuevalues{"key"="value"}spring-doc.cn

只有环境变量名称是小写的,而不是值。 设置 时,Map 包含一个条目。MY_PROPS_VALUES_KEY=VALUEvalues{"key"="VALUE"}spring-doc.cn

缓存

松散绑定使用缓存来提高性能。默认情况下,此缓存仅应用于不可变属性源。 要自定义此行为,例如为可变属性源启用缓存,请使用 ConfigurationPropertyCachingspring-doc.cn

合并复杂类型

在多个位置配置列表时,覆盖的工作原理是替换整个列表。spring-doc.cn

例如,假设对象具有 and 属性,默认情况下为 。 以下示例公开了 :MyPojonamedescriptionnullMyPojoMyPropertiesspring-doc.cn

import java.util.ArrayList;
import java.util.List;

import org.springframework.boot.context.properties.ConfigurationProperties;

@ConfigurationProperties("my")
public class MyProperties {

	private final List<MyPojo> list = new ArrayList<>();

	public List<MyPojo> getList() {
		return this.list;
	}

}
import org.springframework.boot.context.properties.ConfigurationProperties

@ConfigurationProperties("my")
class MyProperties {

	val list: List<MyPojo> = ArrayList()

}

请考虑以下配置:spring-doc.cn

my.list[0].name=my name
my.list[0].description=my description
#---
spring.config.activate.on-profile=dev
my.list[0].name=my another name
my:
  list:
  - name: "my name"
    description: "my description"
---
spring:
  config:
    activate:
      on-profile: "dev"
my:
  list:
  - name: "my another name"

如果配置文件未处于活动状态,则包含一个条目,如前所述。 但是,如果启用了配置文件,则 只包含一个条目(名称 和 描述 )。 此配置不会向列表添加第二个实例,也不会合并项目。devMyProperties.listMyPojodevlistmy another namenullMyPojospring-doc.cn

在多个用户档案中指定 List 时,将使用优先级最高的用户档案(且仅使用该用户档案)。 请考虑以下示例:spring-doc.cn

my.list[0].name=my name
my.list[0].description=my description
my.list[1].name=another name
my.list[1].description=another description
#---
spring.config.activate.on-profile=dev
my.list[0].name=my another name
my:
  list:
  - name: "my name"
    description: "my description"
  - name: "another name"
    description: "another description"
---
spring:
  config:
    activate:
      on-profile: "dev"
my:
  list:
  - name: "my another name"

在前面的示例中,如果配置文件处于活动状态,则包含一个条目(名称为 ,描述为 )。 对于 YAML,逗号分隔列表和 YAML 列表都可用于完全覆盖列表的内容。devMyProperties.listMyPojomy another namenullspring-doc.cn

对于 Map 属性,您可以与从多个源提取的属性值绑定。 但是,对于多个来源中的同一属性,将使用优先级最高的属性。 以下示例公开了 from :Map<String, MyPojo>MyPropertiesspring-doc.cn

import java.util.LinkedHashMap;
import java.util.Map;

import org.springframework.boot.context.properties.ConfigurationProperties;

@ConfigurationProperties("my")
public class MyProperties {

	private final Map<String, MyPojo> map = new LinkedHashMap<>();

	public Map<String, MyPojo> getMap() {
		return this.map;
	}

}
import org.springframework.boot.context.properties.ConfigurationProperties

@ConfigurationProperties("my")
class MyProperties {

	val map: Map<String, MyPojo> = LinkedHashMap()

}

请考虑以下配置:spring-doc.cn

my.map.key1.name=my name 1
my.map.key1.description=my description 1
#---
spring.config.activate.on-profile=dev
my.map.key1.name=dev name 1
my.map.key2.name=dev name 2
my.map.key2.description=dev description 2
my:
  map:
    key1:
      name: "my name 1"
      description: "my description 1"
---
spring:
  config:
    activate:
      on-profile: "dev"
my:
  map:
    key1:
      name: "dev name 1"
    key2:
      name: "dev name 2"
      description: "dev description 2"

如果配置文件未处于活动状态,则包含一个具有键的条目(名称为 ,描述为 )。 但是,如果启用配置文件,则包含两个条目,键(名称为,描述为 )和(名称为 ,描述为 )。devMyProperties.mapkey1my name 1my description 1devmapkey1dev name 1my description 1key2dev name 2dev description 2spring-doc.cn

上述合并规则适用于所有属性源中的属性,而不仅仅是文件。

属性转换

Spring Boot 在绑定到 @ConfigurationProperties bean 时尝试将外部应用程序属性强制为正确的类型。 如果需要自定义类型转换,则可以提供 ConversionService Bean(带有名为 )或自定义属性编辑器(通过 CustomEditorConfigurer Bean)或自定义转换器(将 Bean 定义注释为 @ConfigurationPropertiesBinding)。conversionServicespring-doc.cn

由于此 bean 是在应用程序生命周期的早期请求,因此请确保限制 ConversionService 使用的依赖项。 通常,您需要的任何依赖项在创建时可能未完全初始化。 如果 configuration keys 强制不需要,并且仅依赖于符合 @ConfigurationPropertiesBinding 的自定义转换器,则可能需要重命名自定义 ConversionService

转换持续时间

Spring Boot 专门支持表示持续时间。 如果公开 Duration 属性,则应用程序属性中的以下格式可用:spring-doc.cn

请考虑以下示例:spring-doc.cn

import java.time.Duration;
import java.time.temporal.ChronoUnit;

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.convert.DurationUnit;

@ConfigurationProperties("my")
public class MyProperties {

	@DurationUnit(ChronoUnit.SECONDS)
	private Duration sessionTimeout = Duration.ofSeconds(30);

	private Duration readTimeout = Duration.ofMillis(1000);

	// getters / setters...

	public Duration getSessionTimeout() {
		return this.sessionTimeout;
	}

	public void setSessionTimeout(Duration sessionTimeout) {
		this.sessionTimeout = sessionTimeout;
	}

	public Duration getReadTimeout() {
		return this.readTimeout;
	}

	public void setReadTimeout(Duration readTimeout) {
		this.readTimeout = readTimeout;
	}

}
import org.springframework.boot.context.properties.ConfigurationProperties
import org.springframework.boot.convert.DurationUnit
import java.time.Duration
import java.time.temporal.ChronoUnit

@ConfigurationProperties("my")
class MyProperties {

	@DurationUnit(ChronoUnit.SECONDS)
	var sessionTimeout = Duration.ofSeconds(30)

	var readTimeout = Duration.ofMillis(1000)

}

要指定 30 秒的会话超时,则 和 都是等效的。 可以采用以下任何形式指定 500 毫秒的读取超时:和 。30PT30S30s500PT0.5S500msspring-doc.cn

您还可以使用任何受支持的单位。 这些是:spring-doc.cn

默认单位为毫秒,可以使用 @DurationUnit 覆盖,如上面的示例所示。spring-doc.cn

如果您更喜欢使用构造函数绑定,则可以公开相同的属性,如以下示例所示:spring-doc.cn

import java.time.Duration;
import java.time.temporal.ChronoUnit;

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.bind.DefaultValue;
import org.springframework.boot.convert.DurationUnit;

@ConfigurationProperties("my")
public class MyProperties {

	// fields...
	private final Duration sessionTimeout;

	private final Duration readTimeout;

	public MyProperties(@DurationUnit(ChronoUnit.SECONDS) @DefaultValue("30s") Duration sessionTimeout,
			@DefaultValue("1000ms") Duration readTimeout) {
		this.sessionTimeout = sessionTimeout;
		this.readTimeout = readTimeout;
	}

	// getters...

	public Duration getSessionTimeout() {
		return this.sessionTimeout;
	}

	public Duration getReadTimeout() {
		return this.readTimeout;
	}

}
import org.springframework.boot.context.properties.ConfigurationProperties
import org.springframework.boot.context.properties.bind.DefaultValue
import org.springframework.boot.convert.DurationUnit
import java.time.Duration
import java.time.temporal.ChronoUnit

@ConfigurationProperties("my")
class MyProperties(@param:DurationUnit(ChronoUnit.SECONDS) @param:DefaultValue("30s") val sessionTimeout: Duration,
		@param:DefaultValue("1000ms") val readTimeout: Duration)
如果要升级 Long 属性,请确保定义单位(使用 @DurationUnit)(如果不是毫秒)。 这样做提供了透明的升级路径,同时支持更丰富的格式。

转换期间

除了持续时间之外, Spring Boot 还可以使用Period类型。 应用程序属性中可以使用以下格式:spring-doc.cn

简单格式支持以下单位:spring-doc.cn

Period 类型实际上从未存储周数,它是一个表示 “7 天” 的快捷方式。

转换数据大小

Spring Framework 具有DataSize值类型,该值类型以字节为单位表示大小。 如果公开 DataSize 属性,则应用程序属性中的以下格式可用:spring-doc.cn

请考虑以下示例:spring-doc.cn

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.convert.DataSizeUnit;
import org.springframework.util.unit.DataSize;
import org.springframework.util.unit.DataUnit;

@ConfigurationProperties("my")
public class MyProperties {

	@DataSizeUnit(DataUnit.MEGABYTES)
	private DataSize bufferSize = DataSize.ofMegabytes(2);

	private DataSize sizeThreshold = DataSize.ofBytes(512);

	// getters/setters...

	public DataSize getBufferSize() {
		return this.bufferSize;
	}

	public void setBufferSize(DataSize bufferSize) {
		this.bufferSize = bufferSize;
	}

	public DataSize getSizeThreshold() {
		return this.sizeThreshold;
	}

	public void setSizeThreshold(DataSize sizeThreshold) {
		this.sizeThreshold = sizeThreshold;
	}

}
import org.springframework.boot.context.properties.ConfigurationProperties
import org.springframework.boot.convert.DataSizeUnit
import org.springframework.util.unit.DataSize
import org.springframework.util.unit.DataUnit

@ConfigurationProperties("my")
class MyProperties {

	@DataSizeUnit(DataUnit.MEGABYTES)
	var bufferSize = DataSize.ofMegabytes(2)

	var sizeThreshold = DataSize.ofBytes(512)

}

指定缓冲区大小为 10 MB,并且等效。 可以将 256 字节的大小阈值指定为 或 。1010MB256256Bspring-doc.cn

您还可以使用任何受支持的单位。 这些是:spring-doc.cn

默认单位是 bytes,可以使用 @DataSizeUnit 覆盖,如上面的示例所示。spring-doc.cn

如果您更喜欢使用构造函数绑定,则可以公开相同的属性,如以下示例所示:spring-doc.cn

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.bind.DefaultValue;
import org.springframework.boot.convert.DataSizeUnit;
import org.springframework.util.unit.DataSize;
import org.springframework.util.unit.DataUnit;

@ConfigurationProperties("my")
public class MyProperties {

	// fields...
	private final DataSize bufferSize;

	private final DataSize sizeThreshold;

	public MyProperties(@DataSizeUnit(DataUnit.MEGABYTES) @DefaultValue("2MB") DataSize bufferSize,
			@DefaultValue("512B") DataSize sizeThreshold) {
		this.bufferSize = bufferSize;
		this.sizeThreshold = sizeThreshold;
	}

	// getters...

	public DataSize getBufferSize() {
		return this.bufferSize;
	}

	public DataSize getSizeThreshold() {
		return this.sizeThreshold;
	}

}
import org.springframework.boot.context.properties.ConfigurationProperties
import org.springframework.boot.context.properties.bind.DefaultValue
import org.springframework.boot.convert.DataSizeUnit
import org.springframework.util.unit.DataSize
import org.springframework.util.unit.DataUnit

@ConfigurationProperties("my")
class MyProperties(@param:DataSizeUnit(DataUnit.MEGABYTES) @param:DefaultValue("2MB") val bufferSize: DataSize,
		@param:DefaultValue("512B") val sizeThreshold: DataSize)
如果要升级 Long 属性,请确保定义单位(使用 @DataSizeUnit)(如果它不是字节)。 这样做提供了透明的升级路径,同时支持更丰富的格式。

@ConfigurationProperties验证

Spring Boot 尝试在使用 Spring 的 @Validated 注释注释时验证@ConfigurationProperties类。 您可以直接在 configuration 类上使用 JSR-303 约束 Comments。 为此,请确保 Classpath 上具有兼容的 JSR-303 实现,然后将约束 Comments 添加到字段中,如以下示例所示:jakarta.validationspring-doc.cn

import java.net.InetAddress;

import jakarta.validation.constraints.NotNull;

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.validation.annotation.Validated;

@ConfigurationProperties("my.service")
@Validated
public class MyProperties {

	@NotNull
	private InetAddress remoteAddress;

	// getters/setters...

	public InetAddress getRemoteAddress() {
		return this.remoteAddress;
	}

	public void setRemoteAddress(InetAddress remoteAddress) {
		this.remoteAddress = remoteAddress;
	}

}
import jakarta.validation.constraints.NotNull
import org.springframework.boot.context.properties.ConfigurationProperties
import org.springframework.validation.annotation.Validated
import java.net.InetAddress

@ConfigurationProperties("my.service")
@Validated
class MyProperties {

	var remoteAddress: @NotNull InetAddress? = null

}
您还可以通过使用 @Validated 注释创建配置属性的 @Bean 方法来触发验证。

要确保始终为嵌套属性触发验证,即使未找到任何属性,也必须使用 @Valid 注释关联的字段。 以下示例基于前面的示例:MyPropertiesspring-doc.cn

import java.net.InetAddress;

import jakarta.validation.Valid;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull;

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.validation.annotation.Validated;

@ConfigurationProperties("my.service")
@Validated
public class MyProperties {

	@NotNull
	private InetAddress remoteAddress;

	@Valid
	private final Security security = new Security();

	// getters/setters...

	public InetAddress getRemoteAddress() {
		return this.remoteAddress;
	}

	public void setRemoteAddress(InetAddress remoteAddress) {
		this.remoteAddress = remoteAddress;
	}

	public Security getSecurity() {
		return this.security;
	}

	public static class Security {

		@NotEmpty
		private String username;

		// getters/setters...

		public String getUsername() {
			return this.username;
		}

		public void setUsername(String username) {
			this.username = username;
		}

	}

}
import jakarta.validation.Valid
import jakarta.validation.constraints.NotEmpty
import jakarta.validation.constraints.NotNull
import org.springframework.boot.context.properties.ConfigurationProperties
import org.springframework.validation.annotation.Validated
import java.net.InetAddress

@ConfigurationProperties("my.service")
@Validated
class MyProperties {

	var remoteAddress: @NotNull InetAddress? = null

	@Valid
	val security = Security()

	class Security {

		@NotEmpty
		var username: String? = null

	}

}

您还可以通过创建名为 的 bean 定义来添加自定义 Spring Validator。 应声明 @Bean 方法 。 配置属性验证器是在应用程序生命周期的早期创建的,将 @Bean 方法声明为 static 可以创建 Bean,而不必实例化 @Configuration 类。 这样做可以避免早期实例化可能导致的任何问题。configurationPropertiesValidatorstaticspring-doc.cn

该模块包括一个公开所有 @ConfigurationProperties bean 的端点。 将 Web 浏览器指向或使用等效的 JMX 终端节点。 有关详细信息,请参阅 生产就绪功能 部分。spring-boot-actuator/actuator/configprops

@ConfigurationProperties vs. @Value

@Value 注解是容器的核心功能,它不提供与类型安全配置属性相同的功能。 下表总结了 @ConfigurationProperties@Value 支持的功能:spring-doc.cn

特征 @ConfigurationProperties @Value

松散的装订spring-doc.cn

是的spring-doc.cn

受限(请参阅下面的注释)spring-doc.cn

元数据支持spring-doc.cn

是的spring-doc.cn

spring-doc.cn

SpEL评估spring-doc.cn

spring-doc.cn

是的spring-doc.cn

如果您确实想使用 @Value,我们建议您使用其规范形式 (kebab-case 仅使用小写字母) 引用属性名称。 这将允许 Spring Boot 使用与松散绑定@ConfigurationProperties时相同的逻辑。spring-doc.cn

例如,将从文件以及系统环境中选取 和 form。 如果你改用,则不会被考虑。@Value("${demo.item-price}")demo.item-pricedemo.itemPriceapplication.propertiesDEMO_ITEMPRICE@Value("${demo.itemPrice}")demo.item-priceDEMO_ITEMPRICEspring-doc.cn

如果您为自己的组件定义了一组配置键,我们建议您将它们分组到一个带有 @ConfigurationProperties 注解的 POJO 中。 这样做将为您提供结构化的、类型安全的对象,您可以将其注入到自己的 bean 中。spring-doc.cn

SpEL在解析 Application 属性文件和填充环境时,不会处理这些文件中的表达式。 但是,可以用 @Value 编写表达式。 如果应用程序属性文件中的属性值是表达式,则在通过 @Value 使用时将对其进行计算。SpELSpELspring-doc.cn