| 此版本仍在开发中,尚不被认为是稳定的。对于最新的稳定版本,请使用 Spring Boot 3.5.5! | 
外部化配置
Spring Boot 允许您将配置外部化,以便您可以在不同的环境中使用相同的应用程序代码。 您可以使用各种外部配置源,包括 Java 属性文件、YAML 文件、环境变量和命令行参数。
属性值可以通过使用@Value注释,通过 Spring 的Environment抽象,或者通过@ConfigurationProperties.
Spring Boot 使用非常特殊的PropertySourceorder 的命令,旨在允许合理地覆盖值。
较高的属性源可以覆盖较早的属性源中定义的值。
按以下顺序考虑来源:
- 
默认属性(通过设置 SpringApplication.setDefaultProperties(Map)).
- 
@PropertySource注释@Configuration类。 请注意,此类属性源不会添加到Environment直到刷新应用程序上下文。 这为时已晚,无法配置某些属性,例如logging.*和spring.main.*在刷新开始之前读取。
- 
配置数据(例如 application.properties文件)。
- 
一个 RandomValuePropertySource仅在random.*.
- 
作系统环境变量。 
- 
Java 系统属性 ( System.getProperties()).
- 
JNDI 属性 java:comp/env.
- 
ServletContextinit 参数。
- 
ServletConfiginit 参数。
- 
属性来自 SPRING_APPLICATION_JSON(嵌入在环境变量或系统属性中的内联 JSON)。
- 
命令行参数。 
- 
properties属性。 适用于@SpringBootTest以及用于测试应用程序特定切片的测试注释。
- 
@DynamicPropertySource测试中的注释。
- 
@TestPropertySource测试上的注释。
- 
Devtools 全局设置属性中的 $HOME/.config/spring-boot目录。
配置文件按以下顺序考虑:
- 
打包在 jar 中的应用程序属性 ( application.properties和 YAML 变体)。
- 
打包在jar中的特定于配置文件的应用程序属性( application-{profile}.properties和 YAML 变体)。
- 
打包 jar 外部的应用程序属性 ( application.properties和 YAML 变体)。
- 
打包的 jar 之外的特定于配置文件的应用程序属性 ( application-{profile}.properties和 YAML 变体)。
| 建议对整个应用程序坚持使用一种格式。
如果您有包含两者的配置文件 .properties和 YAML 格式在同一位置,.properties优先。 | 
| 如果使用环境变量而不是系统属性,则大多数作系统不允许使用以句点分隔的键名,但可以改用下划线(例如, SPRING_CONFIG_NAME而不是spring.config.name).
有关详细信息,请参阅从环境变量绑定。 | 
| 如果您的应用程序在 Servlet 容器或应用程序服务器中运行,那么 JNDI 属性(在 java:comp/env) 或 servlet 上下文初始化参数可以代替环境变量或系统属性,或者与环境变量或系统属性一起使用。 | 
为了提供一个具体的例子,假设您开发了一个@Component使用name属性,如以下示例所示:
- 
Java 
- 
Kotlin 
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 中),您可以有一个application.properties文件,该文件为name.
在新环境中运行时,application.properties可以在 jar 外部提供文件,以覆盖name.
对于一次性测试,您可以使用特定的命令行开关(例如java -jar app.jar --name="Spring").
| 这 env和configprops终结点可用于确定属性具有特定值的原因。
可以使用这两个终结点来诊断意外的属性值。
有关详细信息,请参阅生产就绪功能部分。 | 
访问命令行属性
默认情况下,SpringApplication转换任何命令行选项参数(即以 开头的参数,例如----server.port=9000) 设置为property并将它们添加到 SpringEnvironment.
如前所述,命令行属性始终优先于基于文件的属性源。
如果您不希望将命令行属性添加到Environment,您可以使用以下命令禁用它们SpringApplication.setAddCommandLineProperties(false).
JSON 应用程序属性
环境变量和系统属性通常具有限制,这意味着某些属性名称无法使用。 为了帮助解决这个问题,Spring Boot 允许您将属性块编码为单个 JSON 结构。
当您的应用程序启动时,任何spring.application.json或SPRING_APPLICATION_JSON属性将被解析并添加到Environment.
例如,SPRING_APPLICATION_JSON属性可以在 UN*X shell 的命令行中作为环境变量提供:
$ SPRING_APPLICATION_JSON='{"my":{"name":"test"}}' java -jar myapp.jar在前面的示例中,您最终会遇到my.name=test在SpringEnvironment.
也可以将相同的 JSON 作为系统属性提供:
$ java -Dspring.application.json='{"my":{"name":"test"}}' -jar myapp.jar或者,您可以使用命令行参数提供 JSON:
$ java -jar myapp.jar --spring.application.json='{"my":{"name":"test"}}'如果您要部署到经典的 Application Server,您还可以使用名为java:comp/env/spring.application.json.
| 虽然 nullJSON 中的值将添加到生成的属性源中,PropertySourcesPropertyResolver对待null属性作为缺失值。
这意味着 JSON 不能使用null价值。 | 
外部应用程序属性
Spring Boot 将自动查找并加载application.properties和application.yaml应用程序启动时从以下位置发送的文件:
- 
从类路径 - 
类路径根 
- 
类路径 /config包
 
- 
- 
从当前目录 - 
当前目录 
- 
这 config/子目录
- 
的直接子目录 config/子目录
 
- 
该列表按优先级排序(较低项的值覆盖较早的项)。
加载文件中的文档将添加为PropertySource实例到 SpringEnvironment.
如果你不喜欢application作为配置文件名,您可以通过指定spring.config.nameenvironment 属性。
例如,要查找myproject.properties和myproject.yaml文件,您可以按如下方式运行您的应用程序:
$ java -jar myproject.jar --spring.config.name=myproject您还可以使用spring.config.locationenvironment 属性。
此属性接受一个或多个要检查的位置的逗号分隔列表。
以下示例演示如何指定两个不同的文件:
$ java -jar myproject.jar --spring.config.location=\
	optional:classpath:/default.properties,\
	optional:classpath:/override.properties| 使用前缀 optional:如果位置是可选的,并且您不介意它们是否存在。 | 
| spring.config.name,spring.config.location和spring.config.additional-location很早就用于确定必须加载哪些文件。
它们必须定义为环境属性(通常是作系统环境变量、系统属性或命令行参数)。 | 
如果spring.config.location包含目录(与文件相反),它们应该以 结尾。
在运行时,它们将附加从/spring.config.name在加载之前。
中指定的文件spring.config.location直接导入。
| 目录和文件位置值也会展开,以检查特定于配置文件的文件。
例如,如果您有 spring.config.location之classpath:myconfig.properties,您还会发现合适的classpath:myconfig-<profile>.properties文件已加载。 | 
在大多数情况下,每个spring.config.location您添加的项将引用单个文件或目录。
位置按定义的顺序进行处理,后面的位置可以覆盖前面位置的值。
如果您有复杂的位置设置,并且使用特定于配置文件的配置文件,则可能需要提供进一步的提示,以便 Spring Boot 知道应该如何对它们进行分组。
位置组是在同一级别考虑的所有位置的集合。
例如,您可能希望对所有类路径位置进行分组,然后对所有外部位置进行分组。
位置组中的项目应用 分隔。
有关更多详细信息,请参阅“配置文件特定文件”部分中的示例。;
使用spring.config.location替换默认位置。
例如,如果spring.config.location配置为optional:classpath:/custom-config/,optional:file:./custom-config/,考虑的完整位置集为:
- 
optional:classpath:custom-config/
- 
optional:file:./custom-config/
如果您更喜欢添加其他位置而不是替换它们,您可以使用spring.config.additional-location.
从其他位置加载的属性可以覆盖默认位置中的属性。
例如,如果spring.config.additional-location配置为optional:classpath:/custom-config/,optional:file:./custom-config/,考虑的完整位置集为:
- 
optional:classpath:/;optional:classpath:/config/
- 
optional:file:./;optional:file:./config/;optional:file:./config/*/
- 
optional:classpath:custom-config/
- 
optional:file:./custom-config/
通过此搜索排序,您可以在一个配置文件中指定默认值,然后有选择地覆盖另一个配置文件中的这些值。
您可以在application.properties(或您选择的任何其他基本名称spring.config.name) 在默认位置之一。
然后,可以在运行时使用位于其中一个自定义位置的不同文件覆盖这些默认值。
可选地点
默认情况下,当指定的配置数据位置不存在时,Spring Boot 将抛出一个ConfigDataLocationNotFoundException并且您的应用程序将不会启动。
如果您想指定一个位置,但您不介意它是否总是存在,您可以使用optional:前缀。 您可以将此前缀与spring.config.location和spring.config.additional-location属性,以及spring.config.import声明。
例如,一个spring.config.import值optional:file:./myconfig.properties允许您的应用程序启动,即使myconfig.properties文件丢失。
如果您想忽略所有ConfigDataLocationNotFoundException错误并始终继续启动您的应用程序,您可以使用spring.config.on-not-found财产。 将值设置为ignore用SpringApplication.setDefaultProperties(…)或使用系统/环境变量。
通配符位置
如果配置文件位置包含最后一个路径段的字符,则该位置被视为通配符位置。加载配置时,通配符会展开,以便同时检查直接子目录。当配置属性有多个来源时,通配符位置在 Kubernetes 等环境中特别有用。*
例如,如果你有一些 Redis 配置和一些 MySQL 配置,你可能希望将这两部分配置分开,同时要求这两部分都存在于application.properties文件。 这可能会导致两个单独的application.properties挂载在不同位置的文件,例如/config/redis/application.properties和/config/mysql/application.properties. 在这种情况下,通配符位置为config/*/,将导致两个文件都被处理。
默认情况下,Spring Boot 包括config/*/在默认搜索位置中。这意味着/config将搜索 jar 外部的目录。
您可以自己使用通配符位置,并使用spring.config.location和spring.config.additional-location性能。
| 通配符位置必须仅包含一个并以 结尾的搜索位置,即目录或 **/*/<filename>用于文件搜索位置。
带有通配符的位置根据文件名的绝对路径按字母顺序排序。 | 
| 通配符位置仅适用于外部目录。
不能在 classpath:位置。 | 
配置文件特定文件
以及application属性文件,Spring Boot 还将尝试使用命名约定加载特定于配置文件的文件application-{profile}. 例如,如果您的应用程序激活名为prod并使用 YAML 文件,则同时使用application.yaml和application-prod.yaml将被考虑。
特定于配置文件的属性从与标准相同的位置加载application.properties,特定于配置文件的文件始终覆盖非特定文件。
如果指定了多个配置文件,则应用后赢策略。
例如,如果配置文件prod,live由spring.profiles.active属性,值application-prod.properties可以被那些application-live.properties.
| 后赢策略适用于位置组级别。
一个 例如,继续我们的 /cfg application-live.properties /ext application-live.properties application-prod.properties 当我们有一个 
 当我们有 
 | 
这Environment具有一组默认配置文件(默认情况下,[default]),如果未设置活动配置文件,则使用该配置文件。
换句话说,如果没有显式激活配置文件,则属性application-default被考虑。
| 属性文件仅加载一次。 如果您已经直接导入了配置文件特定的属性文件,则不会再次导入该文件。 | 
导入其他数据
应用程序属性可以使用spring.config.import财产。
导入在发现时进行处理,并被视为插入紧邻声明导入的文档下方的附加文档。
例如,您的类路径中可能有以下内容application.properties文件:
- 
Properties 
- 
YAML 
spring.application.name=myapp
spring.config.import=optional:file:./dev.propertiesspring:
  application:
    name: "myapp"
  config:
    import: "optional:file:./dev.properties"这将触发导入dev.properties当前目录中的文件(如果存在此类文件)。
导入的dev.properties将优先于触发导入的文件。
在上面的示例中,dev.properties可以重新定义spring.application.name到不同的值。
无论声明多少次,导入都只会导入一次。
使用“固定”和“导入相对”位置
导入可以指定为固定或导入相对位置。
固定位置始终解析为相同的底层资源,无论spring.config.import属性被声明。
导入相对位置相对于声明spring.config.import财产。
以正斜杠 () 或 URL 样式前缀 (/file:,classpath:等)被认为是固定的。
所有其他位置都被视为进口相对位置。
| optional:在确定位置是固定位置还是导入相对位置时,不考虑前缀。 | 
例如,假设我们有一个/demo包含我们的application.jar文件。
我们可能会添加一个/demo/application.properties文件,内容如下:
spring.config.import=optional:core/core.properties这是一个导入相对位置,因此将尝试加载文件/demo/core/core.properties如果存在的话。
如果/demo/core/core.properties内容如下:
spring.config.import=optional:extra/extra.properties它将尝试加载/demo/core/extra/extra.properties.
这optional:extra/extra.properties相对于/demo/core/core.properties所以完整目录是/demo/core/ + extra/extra.properties.
属性排序
在 properties/yaml 文件中的单个文档中定义导入的顺序无关紧要。 例如,下面的两个示例产生相同的结果:
- 
Properties 
- 
YAML 
spring.config.import=my.properties
my.property=valuespring:
  config:
    import: "my.properties"
my:
  property: "value"- 
Properties 
- 
YAML 
my.property=value
spring.config.import=my.propertiesmy:
  property: "value"
spring:
  config:
    import: "my.properties"在上述两个示例中,来自my.properties文件将优先于触发其导入的文件。
可以在单个spring.config.import钥匙。 位置将按照定义的顺序进行处理,以后导入优先。
| 在适当的情况下,还会考虑导入特定于配置文件的变体。上面的示例将导入 my.properties以及任何my-<profile>.properties变种。 | 
| Spring Boot 包括可插拔的 API,允许支持各种不同的位置地址。默认情况下,您可以导入 Java 属性、YAML 和配置树。 第三方 jar 可以提供对其他技术的支持(不需要文件是本地的)。 例如,您可以想象配置数据来自外部存储,例如 Consul、Apache ZooKeeper 或 Netflix Archaius。 如果您想支持自己的位置,请参阅 | 
导入无扩展名文件
某些云平台无法向卷挂载文件添加文件扩展名。要导入这些无扩展名文件,您需要给 Spring Boot 一个提示,以便它知道如何加载它们。您可以通过将扩展提示放在方括号中来做到这一点。
例如,假设您有一个/etc/config/myconfig您希望作为 yaml 导入的文件。
您可以从application.properties使用以下内容:
- 
Properties 
- 
YAML 
spring.config.import=file:/etc/config/myconfig[.yaml]spring:
  config:
    import: "file:/etc/config/myconfig[.yaml]"使用配置树
在云平台(如 Kubernetes)上运行应用程序时,通常需要读取平台提供的配置值。 出于此类目的使用环境变量并不少见,但这可能有缺点,特别是如果该值应该保密。
作为环境变量的替代方法,许多云平台现在允许您将配置映射到已挂载的数据卷中。
例如,Kubernetes 可以同时卷挂载ConfigMaps和Secrets.
可以使用两种常见的卷挂载模式:
- 
单个文件包含一组完整的属性(通常写为 YAML)。 
- 
多个文件被写入目录树,文件名成为“键”,内容成为“值”。 
对于第一种情况,您可以使用spring.config.import如上所述。
对于第二种情况,您需要使用configtree:前缀,以便 Spring Boot 知道它需要将所有文件公开为属性。
例如,假设 Kubernetes 已挂载以下卷:
etc/
  config/
    myapp/
      username
      password的内容usernamefile 将是一个配置值,而password将是一个秘密。
要导入这些属性,您可以将以下内容添加到application.properties或application.yaml文件:
- 
Properties 
- 
YAML 
spring.config.import=optional:configtree:/etc/config/spring:
  config:
    import: "optional:configtree:/etc/config/"然后,您可以访问或注入myapp.username和myapp.password属性Environment以通常的方式。
| 配置树下的文件夹和文件的名称构成属性名称。
在上面的示例中,要访问属性 username和password,您可以设置spring.config.import自optional:configtree:/etc/config/myapp. | 
| 带有点表示法的文件名也会正确映射。
例如,在上面的示例中,名为 myapp.username在/etc/config将导致myapp.username属性中的Environment. | 
| 配置树值可以绑定到两个字符串 String和byte[]类型取决于预期的内容。 | 
如果要从同一父文件夹导入多个配置树,则可以使用通配符快捷方式。
任何configtree:location 结尾为 将所有直接子项导入为配置树。
与非通配符导入一样,每个配置树下的文件夹和文件的名称构成属性名称。/*/
例如,给定以下卷:
etc/
  config/
    dbconfig/
      db/
        username
        password
    mqconfig/
      mq/
        username
        password您可以使用configtree:/etc/config/*/作为导入位置:
- 
Properties 
- 
YAML 
spring.config.import=optional:configtree:/etc/config/*/spring:
  config:
    import: "optional:configtree:/etc/config/*/"这将添加db.username,db.password,mq.username和mq.password性能。
| 使用通配符加载的目录按字母顺序排序。如果您需要不同的顺序,则应将每个位置列为单独的导入 | 
配置树也可用于 Docker 机密。当 Docker swarm 服务被授予对机密的访问权限时,该机密将装载到容器中。例如,如果名为db.password安装在位置/run/secrets/,您可以制作db.password使用以下命令提供给 Spring 环境:
- 
Properties 
- 
YAML 
spring.config.import=optional:configtree:/run/secrets/spring:
  config:
    import: "optional:configtree:/run/secrets/"属性占位符
中的值application.properties和application.yaml通过现有的Environment当使用它们时,您可以引用以前定义的值(例如,从系统属性或环境变量)。标准${name}property-placeholder 语法可以在值内的任何位置使用。属性占位符还可以使用:将默认值与属性名称分开,例如${name:default}.
以下示例显示了带默认值和不带默认值的占位符的使用:
- 
Properties 
- 
YAML 
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}"假设username属性未在其他地方设置,app.description将具有价值MyApp is a Spring Boot application written by Unknown.
| 您应该始终使用占位符中的规范形式(仅使用小写字母的烤肉串大小写)来引用占位符中的属性名称。这将允许 Spring Boot 使用与松绑定时相同的逻辑  例如 | 
| 您还可以使用此技术创建现有 Spring Boot 属性的“短”变体。 有关详细信息,请参阅“作指南”中的“使用”短“命令行参数部分。 | 
使用多文档文件
Spring Boot允许您将单个物理文件拆分为多个逻辑文档,每个逻辑文档都是独立添加的。文档从上到下按顺序处理。以后的文档可以覆盖在早期文档中定义的属性。
为application.yaml文件,则使用标准的 YAML 多文档语法。三个连续的连字符表示一个文档的结束,以及下一个文档的开始。
例如,以下文件有两个逻辑文档:
spring:
  application:
    name: "MyApp"
---
spring:
  application:
    name: "MyCloudApp"
  config:
    activate:
      on-cloud-platform: "kubernetes"为application.properties提交特殊或#---!---comment 用于标记文档拆分:
spring.application.name=MyApp
#---
spring.application.name=MyCloudApp
spring.config.activate.on-cloud-platform=kubernetes| 属性文件分隔符不得有任何前导空格,并且必须恰好包含三个连字符。分隔符前后的行不得是相同的注释前缀。 | 
| 多文档属性文件通常与激活属性(例如 spring.config.activate.on-profile. 有关详细信息,请参阅下一节。 | 
激活属性
有时,仅在满足某些条件时激活一组给定的属性很有用。例如,您可能具有仅在特定配置文件处于活动状态时才相关的属性。
您可以使用spring.config.activate.*.
以下激活属性可用:
| 属性 | 注意 | 
|---|---|
| 
 | 必须匹配才能使文档处于活动状态的配置文件表达式,或必须至少匹配一个配置文件表达式的列表才能使文档处于活动状态。 | 
| 
 | 这 | 
例如,以下内容指定第二个文档仅在 Kubernetes 上运行时处于活动状态,并且仅当“prod”或“staging”配置文件处于活动状态时才处于活动状态:
- 
Properties 
- 
YAML 
myprop=always-set
#---
spring.config.activate.on-cloud-platform=kubernetes
spring.config.activate.on-profile=prod | staging
myotherprop=sometimes-setmyprop:
  "always-set"
---
spring:
  config:
    activate:
      on-cloud-platform: "kubernetes"
      on-profile: "prod | staging"
myotherprop: "sometimes-set"加密属性
Spring Boot 不提供任何对加密属性值的内置支持,但是,它确实提供了修改 Spring 中包含的值所需的钩子点Environment.
这EnvironmentPostProcessor接口允许您作Environment在应用程序启动之前。
有关详细信息,请参阅在启动之前自定义环境或 ApplicationContext。
如果您需要一种安全的方式来存储凭据和密码,Spring Cloud Vault 项目支持在 HashiCorp Vault 中存储外部化配置。
使用 YAML
YAML 是 JSON 的超集,因此是指定分层配置数据的便捷格式。 这SpringApplication每当你的类路径上有 SnakeYAML 库时,class 就会自动支持 YAML 作为属性的替代方案。
| 如果您使用Starters,则 SnakeYAML 由 spring-boot-starter. | 
将 YAML 映射到属性
YAML 文档需要从其分层格式转换为可与 Spring 一起使用的平面结构Environment. 例如,考虑以下 YAML 文档:
environments:
  dev:
    url: "https://dev.example.com"
    name: "Developer Setup"
  prod:
    url: "https://another.example.com"
    name: "My Cool App"为了从Environment,它们将被扁平化如下:
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 列表也需要扁平化。它们表示为属性键,并[index]取消引用器。例如,考虑以下 YAML:
 my:
  servers:
  - "dev.example.com"
  - "another.example.com"前面的示例将转换为以下属性:
my.servers[0]=dev.example.com
my.servers[1]=another.example.com| 无法使用 @PropertySource或@TestPropertySource附注。 因此,如果您需要以这种方式加载值,则需要使用属性文件。 | 
直接加载 YAML
Spring Framework 提供了两个方便的类,可用于加载 YAML 文档。 这YamlPropertiesFactoryBean将 YAML 加载为Properties和YamlMapFactoryBean将 YAML 加载为Map.
您还可以使用YamlPropertySourceLoader类,如果要将 YAML 加载为 SpringPropertySource.
配置随机值
这RandomValuePropertySource对于注入随机值(例如,注入机密或测试用例)很有用。
它可以生成整数、long、uuid 或字符串,如以下示例所示:
- 
Properties 
- 
YAML 
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]}"这random.int*语法是OPEN value (,max) CLOSE其中OPEN,CLOSE是任何字符和value,max是整数。
如果max,则value是最小值,而max是最大值(不包括)。
配置系统环境属性
Spring Boot 支持为环境属性设置前缀。
如果系统环境由具有不同配置要求的多个 Spring Boot 应用程序共享,这将很有用。
系统环境属性的前缀可以直接在SpringApplication通过调用setEnvironmentPrefix(…)方法。
例如,如果将前缀设置为input,属性,例如remote.timeout将解析为INPUT_REMOTE_TIMEOUT在系统环境中。
| 前缀仅适用于系统环境属性。
上面的示例将继续使用 remote.timeout从其他来源读取属性时。 | 
类型安全配置属性
使用@Value("${property}")注入配置属性的注释有时可能很麻烦,尤其是在您使用多个属性或数据本质上是分层的时。
Spring Boot 提供了一种使用属性的替代方法,允许强类型 Bean 管理和验证应用程序的配置。
JavaBean 属性绑定
可以绑定声明标准 JavaBean 属性的 bean,如以下示例所示:
- 
Java 
- 
Kotlin 
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 定义了以下属性:
- 
my.service.enabled,值为false默认情况下。
- 
my.service.remote-address,具有可以强制的类型String.
- 
my.service.security.username,具有嵌套的“安全”对象,其名称由属性名称决定。 特别是,该类型在那里根本没有使用,而且可能是SecurityProperties.
- 
my.service.security.password.
- 
my.service.security.roles,并收集String默认为USER.
| 在属性名称中使用保留关键字,例如 my.service.import,使用@Name属性字段上的注释。 | 
| 映射到 @ConfigurationPropertiesSpring Boot 中可用的类是公共 API,但类本身的访问器(getter/setter)并不意味着直接使用。 | 
| 这种排列依赖于默认的空构造函数,并且 getter 和 setter 通常是强制性的,因为绑定是通过标准 Java Beans 属性描述符进行的,就像在 Spring MVC 中一样。 在以下情况下,可以省略 setter: 
 有些人使用 Project Lombok 自动添加 getter 和 setter。 确保 Lombok 不会为此类类型生成任何特定的构造函数,因为它会被容器自动用于实例化对象。 最后,仅考虑标准的 Java Bean 属性,不支持绑定静态属性。 | 
构造函数绑定
上一节中的示例可以以不可变的方式重写,如以下示例所示:
- 
Java 
- 
Kotlin 
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>)
}在此设置中,单个参数化构造函数的存在意味着应使用构造函数绑定。
这意味着绑定器将找到一个构造函数,其中包含您希望绑定的参数。
如果您的类有多个构造函数,则@ConstructorBinding注释可用于指定要用于构造函数绑定的构造函数。
要选择退出类的构造函数绑定,必须使用@Autowired或制作private.
Kotlin 开发人员可以使用空的主构造函数来选择退出构造函数绑定。
例如:
- 
Java 
- 
Kotlin 
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.ConfigurationProperties;
@ConfigurationProperties("my")
public class MyProperties {
	// fields...
	final MyBean myBean;
	private String name;
	@Autowired
	public MyProperties(MyBean myBean) {
		this.myBean = myBean;
	}
	// getters / setters...
	public String getName() {
		return this.name;
	}
	public void setName(String name) {
		this.name = name;
	}
}import org.springframework.boot.context.properties.ConfigurationProperties
@ConfigurationProperties("my")
class MyProperties() {
	constructor(name: String) : this() {
		this.name = name
	}
	// vars...
	var name: String? = null
}构造函数绑定可以与记录一起使用。
除非您的记录有多个构造函数,否则无需使用@ConstructorBinding.
构造函数绑定类的嵌套成员(例如Security在上面的示例中)也将通过其构造函数进行绑定。
可以使用以下命令指定默认值@DefaultValue在构造函数参数和记录组件上。
转换服务将应用于强制注释的Stringvalue 设置为缺失属性的目标类型。
参考前面的例子,如果没有属性绑定到Security这MyProperties实例将包含一个null值security.
要使其包含Security即使没有属性绑定到它(使用 Kotlin 时,这也需要username和password参数Security声明为可为 null,因为它们没有默认值),请使用空的@DefaultValue注解:
- 
Java 
- 
Kotlin 
	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或配置属性扫描。
您不能将构造函数绑定与由常规 Spring 机制创建的 bean(例如@Componentbeans,使用@Bean方法或使用@Import) | 
| 要使用构造函数绑定,必须使用 -parameters.
如果您使用 Spring Boot 的 Gradle 插件或使用 Maven 和spring-boot-starter-parent. | 
| 使用 Optional跟@ConfigurationProperties不推荐,因为它主要用作返回类型。
因此,它不太适合配置属性注入。
为了与其他类型的属性保持一致,如果您确实声明了Optional属性,它没有价值,null而不是空的Optional将被绑定。 | 
| 在属性名称中使用保留关键字,例如 my.service.import,使用@Name构造函数参数上的注释。 | 
启用@ConfigurationProperties注释类型
Spring Boot 提供了绑定的基础设施@ConfigurationProperties类型并将它们注册为 bean。
您可以逐类启用配置属性,也可以启用与组件扫描类似的配置属性扫描。
有时,用@ConfigurationProperties可能不适合扫描,例如,如果您正在开发自己的自动配置或想要有条件地启用它们。
在这些情况下,请使用@EnableConfigurationProperties注解。
这可以在任何@Configuration类,如以下示例所示:
- 
Java 
- 
Kotlin 
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- 
Java 
- 
Kotlin 
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类。
默认情况下,将从声明注释的类的包进行扫描。
如果要定义要扫描的特定包,可以按照以下示例所示进行作:
- 
Java 
- 
Kotlin 
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| 当 假设它在 | 
我们建议@ConfigurationProperties只处理环境,特别是不从上下文中注入其他 bean。
对于极端情况,可以使用setter注入或任何*Aware框架提供的接口(例如EnvironmentAware如果您需要访问Environment).
如果您仍然想使用构造函数注入其他 bean,则必须使用@Component并使用基于 JavaBean 的属性绑定。
使用@ConfigurationProperties注释类型
这种配置风格特别适用于SpringApplication外部 YAML 配置,如以下示例所示:
my:
  service:
    remote-address: 192.168.1.1
    security:
      username: "admin"
      roles:
      - "USER"
      - "ADMIN"与@ConfigurationPropertiesbean,您可以像任何其他 bean 一样注入它们,如以下示例所示:
- 
Java 
- 
Kotlin 
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方法。
当您想要将属性绑定到您无法控制的第三方组件时,这样做可能特别有用。
要从Environment属性, 添加@ConfigurationProperties到其 bean 注册,如以下示例所示:
- 
Java 
- 
Kotlin 
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()
}使用another前缀映射到该AnotherComponentbean 的方式与前面类似SomeProperties例。
松绑
Spring Boot 使用一些宽松的绑定规则Environment属性设置为@ConfigurationPropertiesbean,因此不需要Environment属性名称和 Bean 属性名称。
这很有用的常见示例包括破折号分隔的环境属性(例如context-path绑定到contextPath)和大写的环境属性(例如PORT绑定到port).
例如,请考虑以下内容@ConfigurationProperties类:
- 
Java 
- 
Kotlin 
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
}使用上述代码,可以使用以下属性名称:
| 属性 | 注意 | 
|---|---|
| 
 | 烤肉盒,推荐用于 | 
| 
 | 标准驼峰命名法语法。 | 
| 
 | 下划线表示法,这是用于 | 
| 
 | 大写格式,使用系统环境变量时建议使用。 | 
| 这 prefix注释的值必须采用 kebab 大小写(小写并以 分隔,例如-my.main-project.person). | 
| 属性来源 | 简单 | 列表 | 
|---|---|---|
| 属性文件 | 驼峰式大小写、烤肉串大小写或下划线表示法 | 使用或逗号分隔值的标准列表语法 | 
| YAML 文件 | 驼峰式大小写、烤肉串大小写或下划线表示法 | 标准 YAML 列表语法或逗号分隔值 | 
| 环境变量 | 大写格式,下划线作为分隔符(请参阅从环境变量绑定)。 | 用下划线括起来的数值(请参阅从环境变量绑定) | 
| 系统属性 | 驼峰式大小写、烤肉串大小写或下划线表示法 | 使用或逗号分隔值的标准列表语法 | 
| 我们建议,如果可能,将属性存储为小写烤肉串格式,例如 my.person.first-name=Rod. | 
绑定贴图
绑定到Map属性,您可能需要使用特殊的括号表示法,以便原始的key价值被保留。
如果键不被 、任何非字母数字字符包围,或[]-.被删除。
例如,考虑将以下属性绑定到Map<String,String>:
- 
Properties 
- 
YAML 
my.map[/key1]=value1
my.map[/key2]=value2
my.map./key3=value3my:
  map:
    "[/key1]": "value1"
    "[/key2]": "value2"
    "/key3": "value3"| 对于 YAML 文件,需要用引号括起来才能正确解析键。 | 
上述属性将绑定到Map跟/key1,/key2和key3作为地图中的按键。
斜杠已从key3因为它没有被方括号包围。
绑定到标量值时,键.在它们中不需要被 包围。
标量值包括枚举和[]java.lang包,除了Object.
捆绑a.b=c自Map<String, String>将保留.并返回带有条目的 Map{"a.b"="c"}.
对于任何其他类型,如果您key包含一个..
例如,绑定a.b=c自Map<String, Object>将返回一个带有条目的地图{"a"={"b"="c"}}而[a.b]=c将返回一个带有条目的地图{"a.b"="c"}.
从环境变量绑定
大多数作系统对可用于环境变量的名称施加了严格的规则。
例如,Linux shell 变量只能包含字母 (a自z或A自Z)、数字 (0自9) 或下划线字符 ()。
按照惯例,Unix shell 变量的名称也将采用大写。_
Spring Boot 的宽松绑定规则尽可能地设计为与这些命名限制兼容。
要将规范表单中的属性名称转换为环境变量名称,您可以遵循以下规则:
- 
替换点 ( .) 带有下划线 ()。_
- 
删除所有破折号 ()。 -
- 
转换为大写。 
例如,配置属性spring.main.log-startup-info将是一个名为SPRING_MAIN_LOGSTARTUPINFO.
绑定到对象列表时也可以使用环境变量。
要绑定到List,则变量名称中的元素编号应用下划线括起来。
例如,配置属性my.service[0].other将使用名为MY_SERVICE_0_OTHER.
对环境变量绑定的支持应用于systemEnvironment属性源,以及名称以-systemEnvironment.
从环境变量绑定映射
当 Spring Boot 将环境变量绑定到属性类时,它会在绑定之前将环境变量名称小写。
大多数时候,这个细节并不重要,除非绑定到Map性能。
中的键Map始终为小写,如以下示例所示:
- 
Java 
- 
Kotlin 
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()
}设置MY_PROPS_VALUES_KEY=value这values Map包含一个{"key"="value"}进入。
只有环境变量名称是小写的,而不是值。
设置MY_PROPS_VALUES_KEY=VALUE这values Map包含一个{"key"="VALUE"}进入。
缓存
宽松绑定使用缓存来提高性能。默认情况下,此缓存仅应用于不可变属性源。
若要自定义此行为,例如,若要为可变属性源启用缓存,请使用ConfigurationPropertyCaching.
合并复杂类型
当列表配置在多个位置时,覆盖的工作原理是替换整个列表。
例如,假设MyPojo对象替换为name和description属性null默认情况下。
以下示例公开了MyPojo对象来自MyProperties:
- 
Java 
- 
Kotlin 
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()
}请考虑以下配置:
- 
Properties 
- 
YAML 
my.list[0].name=my name
my.list[0].description=my description
#---
spring.config.activate.on-profile=dev
my.list[0].name=my another namemy:
  list:
  - name: "my name"
    description: "my description"
---
spring:
  config:
    activate:
      on-profile: "dev"
my:
  list:
  - name: "my another name"如果dev配置文件未激活,MyProperties.list包含一个MyPojo条目,如前所述。
如果dev配置文件,但是,list 仍然只包含一个条目(名称为my another name以及null).
此配置不会添加第二个MyPojo实例添加到列表中,并且它不会合并项目。
当List在多个配置文件中指定,则使用优先级最高的配置文件(并且仅使用该配置文件)。
请考虑以下示例:
- 
Properties 
- 
YAML 
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 namemy:
  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"在前面的示例中,如果dev配置文件处于活动状态,MyProperties.list包含一个 MyPojo条目(名称为my another name以及null).
对于 YAML,逗号分隔的列表和 YAML 列表都可用于完全覆盖列表的内容。
为Map属性,您可以与从多个源提取的属性值绑定。
但是,对于多个源中的同一属性,将使用优先级最高的属性。
以下示例公开了Map<String, MyPojo>从MyProperties:
- 
Java 
- 
Kotlin 
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()
}请考虑以下配置:
- 
Properties 
- 
YAML 
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 2my:
  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"如果dev配置文件未激活,MyProperties.map包含一个带有键的条目key1(名称为my name 1以及my description 1).
如果dev配置文件,但是,map包含两个带有键的条目key1(名称为dev name 1以及my description 1) 和key2(名称为dev name 2以及dev description 2).
| 上述合并规则适用于所有属性源中的属性,而不仅仅是文件。 | 
属性转换
Spring Boot 在绑定到@ConfigurationProperties豆。
如果您需要自定义类型转换,您可以提供ConversionServicebean(一个名为conversionService)或自定义属性编辑器(通过CustomEditorConfigurerbean)或自定义转换器(bean 定义注释为@ConfigurationPropertiesBinding).
| 用于属性转换的 Bean 在应用程序生命周期的早期就被请求,因此请确保限制您的依赖项 | 
| 您可能想要重命名您的自定义 ConversionService如果配置密钥强制不需要它,并且仅依赖于符合@ConfigurationPropertiesBinding.
当对@Bean方法@ConfigurationPropertiesBinding,方法应该是static以避免“Bean 不符合所有 BeanPostProcessors 处理的条件”警告。 | 
转换持续时间
Spring Boot 专门支持表达持续时间。
如果将Duration属性,则应用程序属性中的以下格式可用:
- 
一个常客 long表示(使用毫秒作为默认单位,除非@DurationUnit已指定)
- 
一种更易读的格式,其中值和单位耦合 ( 10s表示 10 秒)
请考虑以下示例:
- 
Java 
- 
Kotlin 
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 秒,30,PT30S和30s都是等价的。
500毫秒的读取超时可以用以下任何一种形式指定:500,PT0.5S和500ms.
您还可以使用任何受支持的单元。 这些都是:
- 
ns纳秒级
- 
us微秒
- 
ms毫秒
- 
s几秒钟
- 
m几分钟
- 
h数小时
- 
d几天
默认单位为毫秒,可以使用@DurationUnit如上面的示例所示。
如果更喜欢使用构造函数绑定,则可以公开相同的属性,如以下示例所示:
- 
Java 
- 
Kotlin 
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类型。
应用程序属性中可以使用以下格式:
- 
一个常规的 int表示(使用天数作为默认单位,除非@PeriodUnit已指定)
- 
一种更简单的格式,其中值和单位对耦合( 1y3d表示 1 年零 3 天)
简单格式支持以下单位:
- 
y多年来
- 
m几个月
- 
w数周
- 
d几天
| 这 Periodtype 实际上从未存储周数,它是一个快捷方式,意思是“7 天”。 | 
转换数据大小
- 
一个常客 long表示(使用字节作为默认单位,除非@DataSizeUnit已指定)
- 
一种更易读的格式,其中值和单位耦合 ( 10MB表示 10 兆字节)
请考虑以下示例:
- 
Java 
- 
Kotlin 
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 兆字节的缓冲区大小,10和10MB是等价的。
256 字节的大小阈值可以指定为256或256B.
您还可以使用任何受支持的单元。 这些都是:
- 
B对于字节
- 
KB对于千字节
- 
MB对于兆字节
- 
GB千兆字节
- 
TB对于 TB
默认单位是字节,可以使用@DataSizeUnit如上面的示例所示。
如果更喜欢使用构造函数绑定,则可以公开相同的属性,如以下示例所示:
- 
Java 
- 
Kotlin 
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 尝试验证@ConfigurationProperties类,每当它们使用 Spring 的@Validated注解。
您可以使用 JSR-303jakarta.validation约束注释。
为此,请确保您的类路径上有一个合规的 JSR-303 实现,然后向字段添加约束注释,如以下示例所示:
- 
Java 
- 
Kotlin 
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
}| 您还可以通过注释 @Bean使用@Validated. | 
要将验证级联到嵌套属性,必须使用@Valid.
以下示例基于前面的内容构建MyProperties例:
- 
Java 
- 
Kotlin 
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
	}
}您还可以添加自定义 SpringValidator通过创建一个名为configurationPropertiesValidator.
这@Bean方法应声明static.
配置属性验证器是在应用程序生命周期的早期创建的,并声明@Bean方法作为 static 可以创建 bean,而无需实例化@Configuration类。
这样做可以避免早期实例化可能导致的任何问题。
| 这 spring-boot-actuator模块包含一个端点,该端点将所有@ConfigurationProperties豆。
将 Web 浏览器指向/actuator/configprops或使用等效的 JMX 端点。
有关详细信息,请参阅生产就绪功能部分。 | 
@ConfigurationProperties与@Value
这@Value注释是核心容器功能,它不提供与类型安全配置属性相同的功能。
下表汇总了@ConfigurationProperties和@Value:
| 特征 | @ConfigurationProperties | @Value | 
|---|---|---|
| 是的 | 有限(见下面的注释) | |
| 是的 | 不 | |
| 
 | 不 | 是的 | 
| 如果您确实想使用 例如 | 
如果您为自己的组件定义了一组配置键,我们建议您将它们分组到一个 POJO 中,并用@ConfigurationProperties.
这样做将为您提供结构化的、类型安全的对象,您可以将其注入到您自己的 bean 中。