附录 B. 配置元数据

Spring Boot jar 包含元数据文件,它们提供所有支持的配置属性的详细信息。这些文件被设计成让 IDE 开发人员在用户处理 application.properties 或 application.yml 文件时提供上下文帮助和代码补全。

大多数元数据文件是在编译时通过处理 @ConfigurationProperties 注解的所有项自动生成的。然而,可以手动地为角落的示例或更高级的用例编写元数据的一部分。

B.1 元数据格式

配置元数据文件位于 META-INF/spring-configuration-metadata.json 下的 jar 中。它们使用一种简单的 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 mode. This is actually a shortcut for the \"hibernate.hbm2ddl.auto\" property.",
		  "sourceType": "org.springframework.boot.autoconfigure.orm.jpa.JpaProperties$Hibernate"
	}
	...
],"hints": [
	{
		"name": "spring.jpa.hibernate.ddl-auto",
		"values": [
			{
				"value": "none",
				"description": "Disable DDL handling."
			},
			{
				"value": "validate",
				"description": "Validate the schema, make no changes to the database."
			},
			{
				"value": "update",
				"description": "Update the schema if necessary."
			},
			{
				"value": "create",
				"description": "Create the schema and destroy previous data."
			},
			{
				"value": "create-drop",
				"description": "Create and then destroy the schema at the end of the session."
			}
		]
	}
]}

每个属性是用户用给定值指定的配置项。例如,可以在 application.properties 中指定 server.port 和 server.address,如下:

server.port=9090
server.address=127.0.0.1

“groups” 是较高级别的项,它们本身不指定值,而是为属性提供上下文分组。例如,server.port 和 server.address 属性是 server group 的一部分。

[Note] Note

并不是每一个属性都必须有一个租。一些属性可能存在于它们自己中。

最后,“hints” 是用来帮助用户配置给定属性的附加信息。例如,当开发人员配置 spring.jpa.hibernate.ddl-auto 属性时,工具可以使用这些提示为 none、validate、update、create, 和 create-drop 的值提供一些自动完成帮助。

B.1.1 group 属性

groups 数组中包含的 JSON 对象可以包含下表所示的属性:

名称 类型 目的

name

String

group 的全称。此属性是强制性的。

type

String

group 的数据类型的类名。例如,如果该 group 基于用 @ConfigurationProperties 注解的类,则该属性将包含该类的完全限定名称。如果它是基于 @Bean 方法,则是该方法的返回类型。如果不知道类型,则可以省略属性。

description

String

可以向用户显示的 group 的简短描述。如果没有描述可用,则可以省略。建议描述是短段落,第一行提供简洁的摘要。描述中的最后一行应该以句号(.)结尾。

sourceType

String

提供此组的源的类名。例如,如果该组基于以 @ConfigurationProperties 注解的 @Bean 方法,则此属性将包含包含该方法的 @Configuration 类的完全限定名。如果不知道源类型,则可以省略属性。

sourceMethod

String

产出这个组的方法的全名(包括括号和参数类型)(例如,注解为 @Bean 方法的 @ConfigurationProperties 的名称)。如果不知道源方法,则可以省略。

B.1.2 Property 属性

properties 数组中包含的 JSON 对象可以包含下表中描述的属性:

名称 类型 目的

name

String

property 的全称。名称是以小写并分开的形式(例如,server.address)。此属性是强制性的。

type

String

property 的数据类型(例如 java.lang.String)的完整签名,但也有完整的泛型类型(如 java.util.Map<java.util.String,acme.MyEnum>)。你可以使用此属性来指导用户输入可以输入的值类型。为了保持一致性,一个原语的类型是通过使用它的包装器对应物来指定的(例如,boolean 变为 java.lang.Boolean)。注意,这个类可能是一个复杂的类型,当值被绑定时,它会从字符串转换。如果不知道类型,则可以省略。

description

String

可以向用户显示的 property 的简短描述。如果没有描述可用,则可以省略。建议描述是短段落,第一行提供简洁的摘要。描述中的最后一行应该以句号(.)结尾。

sourceType

String

提供 property 的源的类名。例如,如果该 property 基于以 @ConfigurationProperties 注解的类,则此属性将包含包含该类的完全限定名。如果不知道源类型,则可以省略属性。

defaultValue

Object

默认值,如果未指定属性,则使用该值。如果属性的类型是数组,那么它可以是一个值数组。如果默认值未知,则可以省略。

deprecation

Deprecation

指定属性是否被弃用。如果字段不被弃用,或者如果不知道该信息,则可以省略。下一个表提供了关于弃用属性的更多细节。

每个属性元素的弃权属性中包含的 JSON 对象可以包含以下属性:

名称 类型 目的

level

String

弃用的程度,它可以是warning(默认)或 error。当属性具有警告弃用级别时,它仍然应该绑定在环境中。但是,当它具有错误弃用级别时,该属性将不再被管理,并且不会被绑定。

reason

String

为何弃用属性的原因的简短描述。如果没有原因可用,则可以省略。建议描述是短段落,第一行提供简洁的摘要。描述中的最后一行应该以句号(.)结尾。

replacement

String

替换此已弃用属性的属性全称。如果没有对该属性的替换,则可以省略该属性。

[Note] Note

在 Spring Boot 1.3 之前,可以使用单个已弃用的布尔属性而不是弃用元素。这仍然以弃用的方式支持,并且不再被使用。如果没有理由和替换可用,则应该设置空的弃用对象。

还可以通过将 @DeprecatedConfigurationProperty 注解添加到公开已弃用属性的 getter,在代码中声明性地指定弃用。例如,假定 app.acme.target 属性弄错了,并被重命名为 app.acme.name。下面的示例展示如何处理这种情况:

@ConfigurationProperties("app.acme")
public class AcmeProperties {

	private String name;

	public String getName() { ... }

	public void setName(String name) { ... }

	@DeprecatedConfigurationProperty(replacement = "app.acme.name")
	@Deprecated
	public String getTarget() {
		return getName();
	}

	@Deprecated
	public void setTarget(String target) {
		setName(target);
	}
}
[Note] Note

没有办法设定级别。由于代码仍在处理该属性,因此总是假定警告。

前面的代码确保已弃权的属性仍然有效(委派到后台的名称属性)。一旦可以从公共 API 中删除 getTarget 和 setTarget 方法,元数据中的自动弃用提示也就消失了。如果希望保留提示,则添加具有 error 弃用级别的手动元数据可确保用户仍然了解该属性。当提供替换时,这样做特别有用。

B.1.3 Hint 属性

hints 数组中包含的 JSON 对象可以包含下表所示的属性:

名称 类型 目的

name

String

此提示引用的属性的全称。名称是以小写周期分隔的形式(如 spring.mvc.servlet.path)。如果属性引用映射(例如 system.contexts),则提示要么应用于映射的键(system.context.keys),要么应用于映射的值(system.context.values)。此属性是强制性的。

values

ValueHint[]

由 ValueHint 对象定义的有效值列表(下表中描述)。每个条目定义了该值并可以进行描述。

providers

ValueProvider[]

由 ValueProvider 对象定义的提供程序列表(在本文档后面描述)。每个条目定义提供程序的名称及其参数,如果有的话。

每个提示元素的 values 属性中包含的 JSON 对象可以包含下表中描述的属性:

名称 类型 目的

value

Object

提示引用的元素的有效值。如果属性的类型是一个数组,那么它也可以是一个值数组。此属性是强制性的。

description

String

用户可以引用的值的简短描述。如果没有描述可用,则可以省略。建议描述是短段落,第一行提供简洁的摘要。描述中的最后一行应该以句号(.)结尾。

每个提示元素的 providers 属性中包含的 JSON 对象可以包含下表中描述的属性:

名称 类型 目的

name

String

提供给提示所引用元素的附加内容帮助的提供程序的名称。

parameters

JSON object

提供程序支持的任何附加参数(检查提供程序的文档以获取更多信息)。

B.1.4 重复的元数据项

具有相同属性和组名称的对象可以在元数据文件中出现多次。例如,可以将两个单独的类绑定到同一个前缀,每个前缀具有可能重叠的属性名。虽然多次出现在元数据中的相同名称不应该是常见的,但是元数据的消费者应该注意确保它们并支持。

B.2 提供手动提示

为了改善用户体验并进一步帮助用户配置给定属性,可以提供附加元数据:

  • 描述属性的潜在值列表。
  • 关联提供者,以将定义良好的语义附加到属性,从而工具可以根据项目的上下文发现潜在值的列表。

B.2.1 值提示

每个提示的 name 属性是指属性的名称。在前面所示的初始示例中,我们为 spring.jpa.hibernate.ddl-auto 属性提供了五个值:none、validate、update、create 和 create-drop。每个值也可以有描述。

如果你的属性属于 Map 类型,则可以为键和值提供提示(但不为映射本身提供提示)。特殊的 .keys 和 .values 后缀必须分别表示键和值。

假设一个 sample.contexts 将 magic String 值映射到一个整数,如下面的例子所示:

@ConfigurationProperties("sample")
public class SampleProperties {

	private Map<String,Integer> contexts;
	// getters and setters
}

magic 是(在这个例子中)是 sample1 和 sample2。为了为键提供额外的内容帮助,你可以向模块的手动元数据添加以下 JSON:

{"hints": [
	{
		"name": "sample.contexts.keys",
		"values": [
			{
				"value": "sample1"
			},
			{
				"value": "sample2"
			}
		]
	}
]}
[Tip] Tip

我们建议你使用一个枚举来代替这两个值。如果 IDE 支持它,这是迄今为止最有效的自动完成方法。

B.2.2 值提供者

提供者是将语义附加到属性的强大方法。在本节中,我们定义了你可以使用自己的提示的官方提供者。但是,你最喜欢的 IDE 可以实现其中的一些或全部。而且,它最终可以提供它自己的。

[Note] Note

由于这是一个新特性,IDE 供应商必须追赶它的工作原理。收纳时间自然不同。

下表总结了支持提供者的列表:

名称 描述

any

允许提供任何附加值。

class-reference

自动完成项目中可用的类。通常由目标参数指定的基类约束。

handle-as

处理属性,好像它是由强制目标参数定义的类型定义的。

logger-name

自动完成有效记录器名称。通常,当前项目中可用的包和类名可以自动完成。

spring-bean-reference

自动完成当前项目中可用的bean名称。通常由目标参数指定的基类约束。

spring-profile-name

自动完成项目中可用的 Spring 配置文件名称。

[Tip] Tip

对于给定的属性,只有一个提供者可以是激活的,但是如果它们可以以某种方式管理所有的属性,则可以指定多个提供者。确保首先放置最强大的提供者,因为 IDE 必须使用 JSON 部分中第一个可以处理的提供者。如果没有支持给定属性的提供程序,也不提供特殊的内容辅助。

Any

特殊的 any 提供者值允许提供任何附加值。如果支持,则应使用基于属性类型的正则值验证。

如果你有一个值列表,并且任何额外的值仍然应该被认为是有效的,则通常使用此提供者。

下面的示例为 system.state 提供了 on 和 off 作为自动完成的值:

{"hints": [
	{
		"name": "system.state",
		"values": [
			{
				"value": "on"
			},
			{
				"value": "off"
			}
		],
		"providers": [
			{
				"name": "any"
			}
		]
	}
]}

注意,在前面的示例中,也允许任何其他值。

Class Reference

class-reference 提供者自动完成项目中可用的类。此提供者支持以下参数:

参数 类型 默认值 描述

target

String (Class)

none

应该分配给所选值的类的完全限定名。通常用于筛选非候选类。请注意,此信息可以由类型本身通过公开具有适当上界的类来提供。

concrete

boolean

true

指定是否仅将具体类视为有效候选。

以下元数据片段对应于定义要使用的 JspServlet 类名的标准 server.servlet.jsp.class-name 属性:

{"hints": [
	{
		"name": "server.servlet.jsp.class-name",
		"providers": [
			{
				"name": "class-reference",
				"parameters": {
					"target": "javax.servlet.http.HttpServlet"
				}
			}
		]
	}
]}

Handle As

handle-as 作为提供者,你可以将属性的类型替换为更高级的类型。这通常发生在属性具有 java.lang.String 类型时,因为你不希望配置类依赖于可能不在类路径上的类。此提供者支持以下参数:

参数 类型 默认值 描述

target

String (Class)

none

要考虑的类型的完全限定名称。此参数是强制性的。

可以使用以下类型:

  • 任何 java.lang.Enum:列出属性的可能值。(我们建议使用 Enum 类型定义属性,因为 IDE 自动完成值不需要进一步的提示)。
  • java.nio.charset.Charset:支持自动完成 charset/encoding 值(如 UTF-8)
  • java.util.Locale: 区域设置的自动完成(如 en_US)
  • org.springframework.util.MimeType:支持内容类型值(如 text/plain)的自动完成
  • org.springframework.core.io.Resource:支持自动完成 Spring 的资源抽象,以引用文件系统或类路径上的文件。(如 classpath:/sample.properties)
[Tip] Tip

如果可以提供多个值,请使用 Collection 或 Array 类型来教导 IDE。

下面的元数据片段对应于标准 spring.liquibase.change-log 属性,该属性定义要使用的 changelog 的路径。它实际上在内部用作 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"
				}
			}
		]
	}
]}

Logger Name

logger-name 提供这自动完成有效记录器名称。通常,当前项目中可用的包和类名可以自动完成。特定的框架可以有额外的魔术记录器名称,也可以支持。

由于日志记录器名称可以是任意名称,因此此提供者应该允许任何值,但是可以突出显示项目的类路径中不可用的有效包和类名称。

下面的元数据片段对应于标准 logging.level 属性。键是记录器名称,值对应于标准日志级别或任何自定义级别。

{"hints": [
	{
		"name": "logging.level.keys",
		"values": [
			{
				"value": "root",
				"description": "Root logger used to assign the default logging level."
			}
		],
		"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"
			}
		]
	}
]}

Spring Bean Reference

spring-bean-reference 提供者自动完成当前项目配置中定义的 bean。此提供者支持以下参数:

参数 类型 默认值 描述

target

String (Class)

none

应该被分配给候选的 bean 类的完全限定名。通常用于筛选非候选 bean。

以下元数据片段对应于定义要使用的 MBeanServer bean 名称的标准 spring.jmx.server 属性:

{"hints": [
	{
		"name": "spring.jmx.server",
		"providers": [
			{
				"name": "spring-bean-reference",
				"parameters": {
					"target": "javax.management.MBeanServer"
				}
			}
		]
	}
]}
[Note] Note

绑定器不知道元数据。如果提供了提示,仍然需要使用 ApplicationContext 将 bean 名称转换为实际的 bean 引用。

Spring Profile Name

spring-profile-name 提供者自动完成当前项目配置中定义的 Spring 配置文件。

以下元数据片段对应于标准 spring.profiles.active 属性,该属性定义 Spring 配置文件的名称以便启用:

{"hints": [
	{
		"name": "spring.profiles.active",
		"providers": [
			{
				"name": "spring-profile-name"
			}
		]
	}
]}

B.3 使用注解处理器生成自己的元数据

通过使用 spring-boot-configuration-processor jar,你可以很容易地从 @ConfigurationProperties 注解的项生成你自己的配置元数据文件。jar 包含一个 Java 注解处理器,它在你的项目被编译时调用。要使用处理器,需要包含对 spring-boot-configuration-processor 的依赖项。

在 Maven 中,依赖项应该声明为可选的,如下面的示例所示:

<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-configuration-processor</artifactId>
	<optional>true</optional>
</dependency>

对于 Gradle 4.5 和更早版本,依赖关系应该在 compileOnly 配置中声明,如下面的示例所示:

dependencies {
	compileOnly "org.springframework.boot:spring-boot-configuration-processor"
}

对于 Gradle 4.6 以及更高版本,依赖关系应该在 annotationProcessor 配置中声明,如下面的示例所示:

dependencies {
	annotationProcessor "org.springframework.boot:spring-boot-configuration-processor"
}

如果你使用的是 additional-spring-configuration-metadata.json 文件,那么 compileJava 任务应该被配置为依赖于 processResources 任务,如下面的示例所示:

compileJava.dependsOn(processResources)

这种依赖性确保在编译过程中注解处理器运行时附加元数据可用。

处理器选择用 @ConfigurationProperties 注解的类和方法。配置类中的字段值的 Javadoc 用于填充描述属性。

[Note] Note

你应该只使用带有 @ConfigurationProperties 字段 Javadoc 的简单文本,因为它们在被添加到 JSON 之前不被处理。

属性是通过标准 getter 和 setter 的存在来发现的,它们具有对集合类型的特殊处理(即使只存在 getter 也会检测到)。注解处理器还支持使用 @Data、@Getter 和 @Setter lombok 注解。

[Note] Note

如果在项目中使用 AspectJ,则需要确保注解处理器只运行一次。有几种方法可以做到这一点。使用 Maven,你可以显式配置 maven-apt-plugin,并将依赖关系仅添加到注解处理器中。你还可以让 AspectJ 插件运行 maven-compiler-plugin 配置中的所有处理并禁用注解处理,如下所示:

<plugin>
	<groupId>org.apache.maven.plugins</groupId>
	<artifactId>maven-compiler-plugin</artifactId>
	<configuration>
		<proc>none</proc>
	</configuration>
</plugin>

B.3.1 嵌套属性

注解处理器自动将内部类视为嵌套属性。考虑下面的类:

@ConfigurationProperties(prefix="server")
public class ServerProperties {

	private String name;

	private Host host;

	// ... getter and setters

	public static class Host {

		private String ip;

		private int port;

		// ... getter and setters

	}

}

前面的示例为 server.name、server.host.ip 和 server.host.port 属性生成元数据信息。你可以在字段上使用 @NestedConfigurationProperty 注解来指示应该将常规(非内部)类视为嵌套类。

[Tip] Tip

这对集合和映射没有影响,因为这些类型是自动标识的,并且为每个类型生成一个元数据属性。

B.3.2 添加附加的元数据

Spring Boot 的配置文件处理非常灵活,并且通常存在不绑定 @ConfigurationProperties bean 的属性。你还可能需要调整现有键的某些属性。为了支持这些情况并允许你提供定制的提示,注解处理器自动将 META-INF/additional-spring-configuration-metadata.json 中的项合并到主元数据文件中。

如果引用已自动检测到的属性,则重写描述、默认值和弃用信息(如果指定)。如果当前模块中未标识手动属性声明,则将其添加为新属性。

附加的 additional-spring-configuration-metadata.json 文件的格式与常规的 spring-configuration-metadata.json 文件完全相同。附加属性文件是可选的。如果没有任何附加属性,请不要添加文件。