Spring Boot的JAR包包含元数据文件,提供了所有支持的配置属性的详细信息。这些文件旨在让IDE开发人员在用户处理application.properties
或application.yaml
文件时提供上下文帮助和“代码完成”功能。
大部分元数据文件是在编译时通过处理所有使用@ConfigurationProperties
注解的项目自动生成的。然而,也可以针对特殊情况或更高级的用例手动编写部分元数据。
1. 元数据格式
配置元数据文件位于jar包中的 META-INF/spring-configuration-metadata.json
。它们使用JSON格式,其中项目分为“groups”或“properties”类别,并且附加值提示分为“hints”类别,如下例所示:
{"groups": [
{
"name": "server",
"type": "org.springframework.boot.autoconfigure.web.ServerProperties",
"sourceType": "org.springframework.boot.autoconfigure.web.ServerProperties"
},
{
"name": "spring.jpa.hibernate",
"type": "org.springframework.boot.autoconfigure.orm.jpa.JpaProperties$Hibernate",
"sourceType": "org.springframework.boot.autoconfigure.orm.jpa.JpaProperties",
"sourceMethod": "getHibernate()"
}
...
],"properties": [
{
"name": "server.port",
"type": "java.lang.Integer",
"sourceType": "org.springframework.boot.autoconfigure.web.ServerProperties"
},
{
"name": "server.address",
"type": "java.net.InetAddress",
"sourceType": "org.springframework.boot.autoconfigure.web.ServerProperties"
},
{
"name": "spring.jpa.hibernate.ddl-auto",
"type": "java.lang.String",
"description": "DDL 模式。实际上,这是“hibernate.hbm2ddl.auto”属性的快捷方式。",
"sourceType": "org.springframework.boot.autoconfigure.orm.jpa.JpaProperties$Hibernate"
}
...
],"hints": [
{
"name": "spring.jpa.hibernate.ddl-auto",
"values": [
{
"value": "none",
"description": "禁用 DDL 处理。"
},
{
"value": "validate",
"description": "验证模式,不对数据库进行更改。"
},
{
"value": "update",
"description": "如有必要,更新模式。"
},
{
"value": "create",
"description": "创建模式并销毁先前的数据。"
},
{
"value": "create-drop",
"description": "在会话结束时创建然后销毁模式。"
}
]
}
]}
每个“property”是用户指定的配置项,具有给定的值。例如,server.port
和 server.address
可能在您的 application.properties
/application.yaml
中指定如下:
server.port=9090
server.address=127.0.0.1
server:
port: 9090
address: 127.0.0.1
“groups”是高级别项目,它们本身不指定值,而是为属性提供上下文分组。例如,server.port
和 server.address
属性属于 server
组。
并非每个“property”都必须有一个“group”。有些属性可能独立存在。 |
最后,“hints”是用于帮助用户配置给定属性的附加信息。例如,当开发人员配置 spring.jpa.hibernate.ddl-auto
属性时,工具可以使用提示为 none
、validate
、update
、create
和 create-drop
值提供一些自动完成帮助。
1.1. 组属性
groups
数组中包含的 JSON 对象可以包含以下表中显示的属性:
名称 | 类型 | 目的 |
---|---|---|
|
字符串 |
组的完整名称。此属性是必需的。 |
|
字符串 |
组的数据类型的类名。例如,如果组基于带有 |
|
字符串 |
可以显示给用户的组的简短描述。如果没有描述可用,则可以省略。建议描述为简短段落,第一行提供简明摘要。描述的最后一行应以句号( |
|
字符串 |
贡献此组的源的类名。例如,如果组基于带有 |
|
字符串 |
贡献此组的方法的完整名称(包括括号和参数类型)(例如,带有 |
1.2. 属性属性
在properties
数组中包含的JSON对象可以包含以下表格中描述的属性:
名称 | 类型 | 目的 |
---|---|---|
|
字符串 |
属性的完整名称。名称以小写句点分隔的形式表示(例如, |
|
字符串 |
属性数据类型的完整签名(例如, |
|
字符串 |
属性的简短描述,可显示给用户。如果没有描述可用,则可以省略。建议描述为简短段落,第一行提供简洁摘要。描述的最后一行应以句号( |
|
字符串 |
贡献此属性的源的类名。例如,如果属性来自使用 |
|
对象 |
默认值,如果未指定属性,则使用。如果属性的类型是数组,则可以是一个值的数组。如果默认值未知,则可以省略。 |
|
弃用 |
指定属性是否已弃用。如果字段未弃用或者该信息未知,则可以省略。下一个表格提供了有关 |
每个properties
元素的deprecation
属性中包含的JSON对象可以包含以下属性:
名称 | 类型 | 目的 |
---|---|---|
|
字符串 |
弃用级别,可以是 |
|
字符串 |
属性被弃用的原因的简要描述。如果没有原因可用,则可以省略。建议描述为简短段落,第一行提供简洁摘要。描述的最后一行应以句号( |
|
字符串 |
替换此弃用属性的属性的完整名称。如果没有此属性的替代项,则可以省略。 |
|
字符串 |
属性弃用的版本。可以省略。 |
在Spring Boot 1.3之前,可以使用单个deprecated 布尔属性代替deprecation 元素。这仍以一种不推荐的方式支持,并且不应再使用。如果没有原因和替代项可用,则应设置一个空的deprecation 对象。 |
@DeprecatedConfigurationProperty
注解在代码中声明弃用。例如,假设
my.app.target
属性令人困惑,并且已重命名为
my.app.name
。以下示例显示了如何处理该情况:
@ConfigurationProperties("my.app")
public class MyProperties {
private String name;
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
@Deprecated
@DeprecatedConfigurationProperty(replacement = "my.app.name")
public String getTarget() {
return this.name;
}
@Deprecated
public void setTarget(String target) {
this.name = target;
}
}
无法设置level 。始终假定为warning ,因为代码仍在处理该属性。 |
上述代码确保弃用属性仍然有效(在后台委托给name
属性)。一旦getTarget
和setTarget
方法可以从您的公共API中删除,元数据中的自动弃用提示也将消失。如果要保留提示,使用具有error
弃用级别的手动元数据确保用户仍然了解该属性。当提供了替代项时,这样做特别有用。
1.3. 提示属性
在hints
数组中包含的JSON对象可以包含以下表格中显示的属性:
名称 | 类型 | 目的 |
---|---|---|
|
字符串 |
此提示所指属性的完整名称。名称以小写句点分隔形式表示(例如 |
|
ValueHint[] |
由 |
|
ValueProvider[] |
由 |
在每个hint
元素的values
属性中包含的JSON对象可以包含以下表格中描述的属性:
名称 | 类型 | 目的 |
---|---|---|
|
对象 |
提示所指元素的有效值。如果属性的类型是数组,则也可以是一个值(或值的数组)。此属性为必填项。 |
|
字符串 |
值的简短描述,可显示给用户。如果没有描述可用,则可以省略。建议描述为简短段落,第一行提供简明摘要。描述的最后一行应以句号( |
在每个hint
元素的providers
属性中包含的JSON对象可以包含以下表格中描述的属性:
名称 | 类型 | 目的 |
---|---|---|
|
字符串 |
用于为提示所指元素提供额外内容辅助的提供者名称。 |
|
JSON对象 |
提供者支持的任何额外参数(查看提供者的文档以获取更多详细信息)。 |
2. 提供手动提示
为了改善用户体验并进一步帮助用户配置给定属性,您可以提供额外的元数据,其中包括:
-
描述属性的潜在值列表。
-
关联提供者,将明确定义的语义附加到属性,以便工具可以根据项目的上下文发现潜在值列表。
2.1. 值提示
每个提示的name
属性都指的是属性的name
。在之前显示的初始示例中,我们为spring.jpa.hibernate.ddl-auto
属性提供了五个值:none
、validate
、update
、create
和create-drop
。每个值也可以有描述。
如果您的属性是Map
类型,您可以为键和值提供提示(但不能为地图本身提供提示)。特殊的.keys
和.values
后缀必须分别指向键和值。
假设my.contexts
将魔术String
值映射到整数,如下例所示:
@ConfigurationProperties("my")
public class MyProperties {
private Map<String, Integer> contexts;
}
魔术值(在此示例中)为sample1
和sample2
。为了为键提供额外的内容辅助,您可以将以下JSON添加到模块的手动元数据中:
{"hints": [
{
"name": "my.contexts.keys",
"values": [
{
"value": "sample1"
},
{
"value": "sample2"
}
]
}
]}
我们建议您对这两个值使用Enum 。如果您的IDE支持,这绝对是自动完成最有效的方法。 |
2.2. 值提供者
提供者是将语义附加到属性的强大方式。在本节中,我们定义了您可以用于自己的提示的官方提供者。但是,您喜爱的IDE可能会实现其中一些,也可能一个都没有。此外,它最终可能会提供自己的。
由于这是一个新功能,IDE供应商必须跟上它的工作方式。采用时间自然会有所不同。 |
以下表格总结了支持的提供者列表:
名称 | 描述 |
---|---|
|
允许提供任何额外的值。 |
|
自动完成项目中可用的类。通常受 |
|
处理属性,就好像它是由强制的 |
|
自动完成有效的记录器名称和记录器组。通常,当前项目中可用的包和类名称以及定义的组也可以自动完成。 |
|
自动完成当前项目中可用的bean名称。通常受 |
|
自动完成项目中可用的Spring配置文件名称。 |
对于给定属性,只能有一个提供者处于活动状态,但是如果它们都可以以某种方式管理属性,则可以指定多个提供者。确保将最强大的提供者放在第一位,因为IDE必须使用它可以处理的JSON部分中的第一个提供者。如果不支持给定属性的提供者,则也不会提供任何特殊的内容辅助。 |
2.2.1. 任意
特殊的any提供者值允许提供任何额外的值。如果支持的话,应该基于属性类型进行常规值验证。
如果您有一个值列表,并且任何额外值仍应被视为有效,则通常会使用此提供者。
以下示例为system.state
提供了on
和off
作为自动完成值:
{"hints": [
{
"name": "system.state",
"values": [
{
"value": "on"
},
{
"value": "off"
}
],
"providers": [
{
"name": "any"
}
]
}
]}
请注意,在上面的示例中,任何其他值也是允许的。
2.2.2. 类引用
class-reference提供者自动完成项目中可用的类。此提供者支持以下参数:
参数 | 类型 | 默认值 | 描述 |
---|---|---|---|
|
|
无 |
应该分配给所选值的类的完全限定名称。通常用于过滤非候选类。请注意,此信息可以由类型本身提供,通过公开具有适当上界的类来提供。 |
|
|
true |
指定是否仅将具体类视为有效候选类。 |
以下元数据片段对应于标准的server.servlet.jsp.class-name
属性,该属性定义要使用的JspServlet
类名:
{"hints": [
{
"name": "server.servlet.jsp.class-name",
"providers": [
{
"name": "class-reference",
"parameters": {
"target": "jakarta.servlet.http.HttpServlet"
}
}
]
}
]}
2.2.3. 处理为
handle-as提供者允许您将属性的类型替换为更高级别的类型。这通常发生在属性具有java.lang.String
类型时,因为您不希望您的配置类依赖于可能不在类路径上的类。此提供者支持以下参数:
参数 | 类型 | 默认值 | 描述 |
---|---|---|---|
|
|
无 |
要考虑属性的类型的完全限定名称。此参数是强制性的。 |
以下类型可用:
-
任何
java.lang.Enum
:列出属性的可能值。(我们建议使用Enum
类型定义属性,因为IDE无需进一步提示即可自动完成值) -
java.nio.charset.Charset
:支持字符集/编码值的自动完成(例如UTF-8
) -
java.util.Locale
:自动完成区域设置(例如en_US
) -
org.springframework.util.MimeType
:支持内容类型值的自动完成(例如text/plain
) -
org.springframework.core.io.Resource
:支持Spring的Resource抽象的自动完成,用于引用文件系统或类路径上的文件(例如classpath:/sample.properties
)
如果可以提供多个值,请使用Collection 或Array类型来向IDE介绍。 |
以下元数据片段对应于标准的spring.liquibase.change-log
属性,该属性定义要使用的变更日志的路径。实际上,它在内部作为org.springframework.core.io.Resource
使用,但不能公开为这样,因为我们需要保留原始的String值以将其传递给Liquibase API。
{"hints": [
{
"name": "spring.liquibase.change-log",
"providers": [
{
"name": "handle-as",
"parameters": {
"target": "org.springframework.core.io.Resource"
}
}
]
}
]}
2.2.4. 日志记录器名称
日志记录器名称提供程序会自动完成有效的日志记录器名称和日志记录器组。通常,可以自动完成当前项目中可用的包和类名称。如果启用了组(默认情况下),并且在配置中标识了自定义日志记录器组,则应为其提供自动完成。特定框架可能还支持额外的魔术日志记录器名称。
此提供程序支持以下参数:
参数 | 类型 | 默认值 | 描述 |
---|---|---|---|
|
|
|
指定是否应考虑已知组。 |
由于日志记录器名称可以是任意名称,因此此提供程序应允许任何值,但可以突出显示项目类路径中不可用的有效包和类名称。
以下元数据片段对应于标准的logging.level
属性。键是日志记录器名称,值对应于标准日志级别或任何自定义级别。由于Spring Boot默认定义了一些日志记录器组,因此为这些组添加了专用值提示。
{"hints": [
{
"name": "logging.level.keys",
"values": [
{
"value": "root",
"description": "用于分配默认日志级别的根日志记录器。"
},
{
"value": "sql",
"description": "包括Hibernate SQL记录器在内的SQL日志记录组。"
},
{
"value": "web",
"description": "包括编解码器在内的Web日志记录组。"
}
],
"providers": [
{
"name": "logger-name"
}
]
},
{
"name": "logging.level.values",
"values": [
{
"value": "trace"
},
{
"value": "debug"
},
{
"value": "info"
},
{
"value": "warn"
},
{
"value": "error"
},
{
"value": "fatal"
},
{
"value": "off"
}
],
"providers": [
{
"name": "any"
}
]
}
]}
2.2.5. Spring Bean 引用
Spring Bean引用提供程序会自动完成在当前项目配置中定义的bean。此提供程序支持以下参数:
参数 | 类型 | 默认值 | 描述 |
---|---|---|---|
|
|
none |
应分配给候选者的bean类的完全限定名称。通常用于过滤非候选bean。 |
以下元数据片段对应于定义要使用的MBeanServer
bean名称的标准spring.jmx.server
属性:
{"hints": [
{
"name": "spring.jmx.server",
"providers": [
{
"name": "spring-bean-reference",
"parameters": {
"target": "javax.management.MBeanServer"
}
}
]
}
]}
绑定器不了解元数据。如果提供了该提示,则仍然需要使用ApplicationContext 将bean名称转换为实际的Bean引用。 |
3. 使用注解处理器生成自己的元数据
您可以通过使用@ConfigurationProperties
注解的项目轻松生成自己的配置元数据文件,方法是使用spring-boot-configuration-processor
jar。该jar包含一个Java注解处理器,在编译项目时被调用。
3.1. 配置注解处理器
要使用该处理器,需要在spring-boot-configuration-processor
上声明依赖。
使用Maven时,依赖应声明为可选的,如下例所示:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
使用Gradle时,依赖应在annotationProcessor
配置中声明,如下例所示:
dependencies {
annotationProcessor "org.springframework.boot:spring-boot-configuration-processor"
}
如果您在项目中使用了additional-spring-configuration-metadata.json
文件,则应配置compileJava
任务依赖于processResources
任务,如下例所示:
tasks.named('compileJava') {
inputs.files(tasks.named('processResources'))
}
此依赖确保在编译过程中注解处理器运行时附加元数据可用。
如果您在项目中使用AspectJ,需要确保注解处理器仅运行一次。有几种方法可以实现这一点。使用Maven,您可以显式配置
|
如果您在项目中使用Lombok,需要确保其注解处理器在 |
3.2. 自动元数据生成
处理器会捕获使用@ConfigurationProperties
注解的类和方法。
如果类具有单个参数化构造函数,则会为每个构造函数参数创建一个属性,除非构造函数带有@Autowired
注解。如果类具有显式使用@ConstructorBinding
注解的构造函数,则会为该构造函数的每个构造函数参数创建一个属性。否则,通过存在标准getter和setter来发现属性,并对集合和映射类型进行特殊处理(即使只有getter也会检测到)。注解处理器还支持使用@Data
、@Value
、@Getter
和@Setter
lombok注解。
考虑以下示例:
@ConfigurationProperties(prefix = "my.server")
public class MyServerProperties {
/**
* 服务器名称。
*/
private String name;
/**
* 要监听的IP地址。
*/
private String ip = "127.0.0.1";
/**
* 要监听的端口。
*/
private int port = 9797;
这里暴露了三个属性,其中my.server.name
没有默认值,my.server.ip
和my.server.port
默认分别为"127.0.0.1"
和9797
。字段上的Javadoc用于填充description
属性。例如,my.server.ip
的描述是"要监听的IP地址"。
在@ConfigurationProperties 字段Javadoc中只能使用纯文本,因为它们在添加到JSON之前不会被处理。 |
注解处理器会应用一些启发式方法从源模型中提取默认值。默认值必须静态提供。特别是,不要引用另一个类中定义的常量。此外,注解处理器无法自动检测Enum
和Collections
的默认值。
对于无法检测到默认值的情况,应提供手动元数据。考虑以下示例:
@ConfigurationProperties(prefix = "my.messaging")
public class MyMessagingProperties {
private List<String> addresses = new ArrayList<>(Arrays.asList("a", "b"));
private ContainerType containerType = ContainerType.SIMPLE;
public enum ContainerType {
SIMPLE, DIRECT
}
}
为了记录上述类中属性的默认值,您可以将以下内容添加到模块的手动元数据中:
{"properties": [
{
"name": "my.messaging.addresses",
"defaultValue": ["a", "b"]
},
{
"name": "my.messaging.container-type",
"defaultValue": "simple"
}
]}
仅需要为现有属性的文档提供附加元数据时,只需要name 属性。 |
3.2.1. 嵌套属性
注解处理器会自动将内部类视为嵌套属性。与在命名空间根部文档化ip
和port
不同,我们可以为其创建一个子命名空间。考虑更新后的示例:
@ConfigurationProperties(prefix = "my.server")
public class MyServerProperties {
private String name;
private Host host;
public static class Host {
private String ip;
private int port;
}
}
上述示例为my.server.name
、my.server.host.ip
和my.server.host.port
属性生成了元数据信息。您可以在字段上使用@NestedConfigurationProperty
注解,以指示常规(非内部)类应被视为嵌套类。
这对集合和映射没有影响,因为这些类型会自动识别,并为每个生成单个元数据属性。 |
3.3. 添加额外元数据
Spring Boot的配置文件处理非常灵活,通常存在未绑定到@ConfigurationProperties
bean的属性。您可能还需要调整现有键的某些属性。为了支持这种情况并让您提供自定义的“提示”,注解处理器会自动将META-INF/additional-spring-configuration-metadata.json
中的项目合并到主元数据文件中。
如果引用了自动检测到的属性,则如果指定了描述、默认值和弃用信息,则会覆盖这些信息。如果在当前模块中未识别手动属性声明,则会将其添加为新属性。
additional-spring-configuration-metadata.json
文件的格式与常规spring-configuration-metadata.json
完全相同。额外属性文件是可选的。如果没有任何额外属性,则不要添加该文件。