Mongoosej.Blog.Software.Programming.Java.Framework.Spring.SpringBoot.Aspect.Configuration Metadata
在使用了spring boot技术的jar包中,在元数据目录下经常能够看到spring-configuration-metadata.json以及additional-spring-configuration-metadata.json这样的文件。这是干什么用的呢,本文就来讲讲这两个文件的作用。
Spring Boot jar 包含元数据文件,这些文件提供了所有受支持的配置属性的详细信息。这些文件旨在让 IDE 开发人员在使用 application.properties 或 application.yml 文件时提供语境帮助和“代码完成”。
The majority of the metadata file is generated automatically at compile time by processing all items annotated with @ConfigurationProperties. However, it is possible to write part of the metadata manually for corner cases or more advanced use cases.
大多数元数据文件是在编译时通过处理所有使用@ConfigurationProperties 注释的项目自动生成的。但是,可以为极端情况或更高级的用例手动编写部分元数据。
上述是Spring官方的解释。简单来说就是/META-INF/spring-configuration-metadata.json和/META-INF/additional-spring-configuration-metadata.json这两个文件是在编译时根据@ConfigurationProperties注解的类自动生成的,这两个文件的目的是帮助开发人员在使用application.properties或者application.yml文件配置属性时,能够清楚如何配置key-value。这就是这两个文件的来源和作用。
思考:STS工具编辑application.properties/application.yml时,属性的自动提示,是否就是从这两个文件中获取的数据?
配置元数据格式
配置元数据文件的解读,放到了下面的json文件注释中。
{
"//":"一个group元素代表了一组属性的信息,描述了一个@ConfigurationProperties所注释的配置属性类"
"groups":[
{
"name":"spring.jpa.hibernate",
"sourceType":"org.springframework.boot.autoconfigure.orm.jpa.HibernateProperties",
"type":"org.springframework.boot.autoconfigure.orm.jpa.HibernateProperties"
},
{
"//":"The full name of the group. This attribute is mandatory."
"//":"组的全名。该属性是强制性的。"
"name":"spring.jpa.hibernate.naming",
"//":"The class name of the source that contributed this group. For example, if the group were based on a @Bean method annotated with @ConfigurationProperties, this attribute would contain the fully qualified name of the @Configuration class that contains the method. If the source type is not known, the attribute may be omitted."
"//":"贡献此组的源的类名。例如,如果组基于使用@ConfigurationProperties 注释的@Bean 方法,则此属性将包含包含该方法的@Configuration 类的完全限定名称。如果源类型未知,则可以省略该属性。"
"sourceType":"org.springframework.boot.autoconfigure.orm.jpa.HibernateProperties",
"//":"The class name of the data type of the group. For example, if the group were based on a class annotated with @ConfigurationProperties, the attribute would contain the fully qualified name of that class. If it were based on a @Bean method, it would be the return type of that method. If the type is not known, the attribute may be omitted."
"//":"组的数据类型的类名。例如,如果组基于使用 @ConfigurationProperties 注释的类,则该属性将包含该类的完全限定名称。如果它基于 @Bean 方法,那么它将是该方法的返回类型。如果类型未知,则可以省略该属性。"
"type":"org.springframework.boot.autoconfigure.orm.jpa.HibernateProperties$Naming"
"//":"The full name of the method (include parenthesis and argument types) that contributed this group (for example, the name of a @ConfigurationProperties annotated @Bean method). If the source method is not known, it may be omitted."
"//":"贡献此组的方法的全名(包括括号和参数类型)(例如,@ConfigurationProperties 注释的 @Bean 方法的名称)。如果源方法未知,则可以省略。"
"sourceMethod":"getNaming()",
}
],
"//":"一个property元素代表了一个属性的信息,描述了一个@ConfigurationProperties所注释的配置属性类中的一个属性"
"properties":[
{
"//":"The full name of the property. Names are in lower-case period separated form (for example, server.address). This attribute is mandatory."
"//":"属性的全名,名称采用小写句点分隔形式(例如 server.address),该属性是强制性的。"
"name":"spring.jpa.hibernate.ddl-auto",
"//":"The class name of the source that contributed this property. For example, if the property were from a class annotated with @ConfigurationProperties, this attribute would contain the fully qualified name of that class. If the source type is unknown, it may be omitted."
"//":"贡献此属性的源的类名。例如,如果属性来自使用 @ConfigurationProperties 注释的类,则此属性将包含该类的完全限定名称。如果源类型未知,则可以省略。"
"sourceType":"org.springframework.boot.autoconfigure.orm.jpa.HibernateProperties",
"//":"The full signature of the data type of the property (for example, java.lang.String) but also a full generic type (such as java.util.Map<java.lang.String,com.example.MyEnum>). You can use this attribute to guide the user as to the types of values that they can enter. For consistency, the type of a primitive is specified by using its wrapper counterpart (for example, boolean becomes java.lang.Boolean). Note that this class may be a complex type that gets converted from a String as values are bound. If the type is not known, it may be omitted."
"//":"属性数据类型的完整签名(例如 java.lang.String),但也是完整的泛型类型(例如 java.util.Map<java.lang.String,com.example.MyEnum>)。您可以使用此属性来指导用户了解他们可以输入的值的类型。为了保持一致性,基本数据类型是通过使用其对应的包装类指定(例如,boolean变为java.lang.Boolean)。请注意,此类可能是一个复杂类型,它在绑定值时从 String转换而来。如果类型未知,则可以省略。"
"type":"java.lang.String",
"//":"A short description of the property that can be displayed to users. If no description is available, it may be omitted. It is recommended that descriptions be short paragraphs, with the first line providing a concise summary. The last line in the description should end with a period (.)."
"//":"可以向用户显示的属性的简短描述。如果没有可用的描述,则可以省略。建议描述是简短的段落,第一行提供简洁的摘要。描述中的最后一行应以句点 (.) 结尾。"
"description":"DDL mode. This is actually a shortcut for the \"hibernate.hbm2ddl.auto\" property. Defaults to \"create-drop\" when using an embedded database and no schema manager was detected. Otherwise, defaults to \"none\"."
"//":"其他key还有:defaultValue、deprecation"
},
{
"name":"spring.jpa.hibernate.naming.implicit-strategy",
"sourceType":"org.springframework.boot.autoconfigure.orm.jpa.HibernateProperties$Naming",
"type":"java.lang.String",
"description":"Fully qualified name of the implicit naming strategy."
},
{
"name":"spring.jpa.hibernate.naming.physical-strategy",
"sourceType":"org.springframework.boot.autoconfigure.orm.jpa.HibernateProperties$Naming",
"type":"java.lang.String",
"description":"Fully qualified name of the physical naming strategy."
},
{
"name":"spring.jpa.hibernate.use-new-id-generator-mappings",
"sourceType":"org.springframework.boot.autoconfigure.orm.jpa.HibernateProperties",
"type":"java.lang.Boolean",
"description":"Whether to use Hibernate's newer IdentifierGenerator for AUTO, TABLE and SEQUENCE. This is actually a shortcut for the \"hibernate.id.new_generator_mappings\" property. When not specified will default to \"true\"."
}
],
"//":"一个hint元素代表了一个属性的提示,描述了一个@ConfigurationProperties所注释的配置属性类中的一个属性的取值范围、含义等信息"
"hints":[
{
"//":"The full name of the property to which this hint refers. Names are in lower-case period-separated form (such as spring.mvc.servlet.path). If the property refers to a map (such as system.contexts), the hint either applies to the keys of the map (system.contexts.keys) or the values (system.contexts.values) of the map. This attribute is mandatory."
"//":"此提示所指的属性的全名。名称采用小写句点分隔形式(例如 spring.mvc.servlet.path)。如果属性引用Map(例如 system.contexts),则提示要么应用于Map的键(system.contexts.keys),要么应用于Map的值(system.contexts.values)。该属性是强制性的。"
"name":"spring.jpa.hibernate.ddl-auto",
"//":"A list of valid values as defined by the ValueHint object. Each entry defines the value and may have a description."
"//":"由ValueHint对象定义的有效值列表。每个条目定义值并且可能有描述。"
"values":[
{
"//":"A valid value for the element to which the hint refers. If the type of the property is an array, it can also be an array of value(s). This attribute is mandatory."
"//":"提示所指元素的有效值。如果属性的类型是一个数组,它也可以是一个值数组。该属性是强制性的。"
"value":"none",
"//":"A short description of the value that can be displayed to users. If no description is available, it may be omitted. It is recommended that descriptions be short paragraphs, with the first line providing a concise summary. The last line in the description should end with a period (.)."
"//":"可以向用户显示的值的简短描述。如果没有可用的描述,则可以省略。建议描述是简短的段落,第一行提供简洁的摘要。描述中的最后一行应以句点 (.) 结尾。"
"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."
}
]
},
{
"name":"spring.jpa.hibernate.naming.implicit-strategy",
"//":"A list of providers as defined by the ValueProvider object. Each entry defines the name of the provider and its parameters, if any."
"//":"由 ValueProvider 对象定义的提供者列表。每个条目定义提供者的名称及其参数(如果有)。"
"providers":[
{
"//":"The name of the provider to use to offer additional content assistance for the element to which the hint refers."
"//":"提供者的名称,用于为提示所指的元素提供额外的内容帮助。"
"name":"class-reference",
"//":"Any additional parameter that the provider supports (check the documentation of the provider for more details)."
"//":"提供者支持的任何附加参数(有关更多详细信息,请查看提供者的文档)。"
"parameters":{
"target":"org.hibernate.boot.model.naming.ImplicitNamingStrategy"
}
}
]
},
{
"name":"spring.jpa.hibernate.naming.physical-strategy",
"providers":[
{
"name":"class-reference",
"parameters":{
"target":"org.hibernate.boot.model.naming.PhysicalNamingStrategy"
}
}
]
}
]
}
简单理解:
- groups:表示一组被@ConfigurationProperties注解的xxxProperties类的描述,一个group就代表对一个xxxProperties类的描述。
- name:可以理解为xxxProperties类的prefix,比如spring.jpa.hibernate。如果group表示的是xxxProperties类中的类类型,则为prefix+类类型变量名,比如spring.jpa.hibernate.naming。
- sourceType:xxxProperties类的全限定名。
- type:xxxProperties类的全限定名。
- properties:表示xxxProperties类中的属性的描述。
- name:加上前缀的属性名称。
- sourceType:xxxProperties类的全限定名。
- type:属性的数据类型
- description:属性的描述,等同于xxxProperties类中属性的java doc内容。
- defaultValue:属性的默认值,等同于xxxProperties类中属性的默认赋值。
- deprecation:属性弃用状态。
- hints:表示xxxProperties类中的属性的帮助提示。
- name:对应属性名。
- values:属性的可选值和值所对应的描述。
- providers:高级用法。
配置元数据生成
如果打包jar时,需要生成配置元数据,需要添加spring-boot-configuration-processor依赖。该 jar 包含一个 Java 注释处理器,它在您的项目编译时被调用,能够获取使用 @ConfigurationProperties 注释的类和方法,根据这些类和方法就可以生成了配置元数据文件/META-INF/spring-configuration-metadata.json。
几点要点:
- 配置属性类中变量的Java doc注释,生成配置元数据中properties中property元素的description。
- 配置属性类中变量的初始赋值,生成配置元数据中properties中property元素的defaultValue。
扩展元数据
扩展元数据,即additional-spring-configuration-metadata.json。
Spring Boot 的配置文件处理非常灵活,通常情况下可能存在未绑定到 @ConfigurationProperties bean 的属性。您可能还需要调整现有key的属性。为了支持这种情况并让您提供自定义“提示”,annotation processor自动将 META-INF/additional-spring-configurationmetadata.json 中的项目合并到主元数据文件中。
If you refer to a property that has been detected automatically, the description, default value, and deprecation information are overridden, if specified. If the manual property declaration is not identified in the current module, it is added as a new property.
如果您引用已自动检测到的属性,则描述、默认值和弃用信息(如果指定)将被覆盖。如果当前模块中未标识手动属性声明,则将其添加为新属性。
The format of the additional-spring-configuration-metadata.json file is exactly the same as the regular spring-configuration-metadata.json. The additional properties file is optional. If you do not have any additional properties, do not add the file.
additional-spring-configuration-metadata.json 文件的格式与常规 spring-configuration-metadata.json 完全相同。附加属性文件是可选的。如果您没有任何其他属性,请不要添加该文件。