文章作者:Tyan 博客:noahsnail.com | CSDN | 简书
24. Externalized Configuration
Spring Boot allows you to externalize your configuration so you can work with the same application code in different environments. You can use properties files, YAML files, environment variables and command-line arguments to externalize configuration. Property values can be injected directly into your beans using the @Value
annotation, accessed via Spring’s Environment
abstraction or bound to structured objects via @ConfigurationProperties
.
Spring Boot允许你进行外部化配置,因此可以将同样的应用代码在不同的环境中运行。你可以使用属性文件,YAML文件,环境变量和命令行参数来进行外部化配置。属性值可以使用@Value
注解直接注入到你的beans中,通过Spring的Environment
抽象或通过@ConfigurationProperties
绑定到结构化对象上来访问。
Spring Boot uses a very particular PropertySource
order that is designed to allow sensible overriding of values. Properties are considered in the following order:
Spring Boot使用非常特别的PropertySource
顺序,这个顺序的设计是为了允许值的合理重写。属性被认为是按照以下顺序:
- Devtools global settings properties on your home directory (
~/.spring-boot-devtools.properties
when devtools is active). @TestPropertySource
annotations on your tests.@SpringBootTest#properties
annotation attribute on your tests.- Command line arguments.
- Properties from
SPRING_APPLICATION_JSON
(inline JSON embedded in an environment variable or system property) ServletConfig
init parameters.ServletContext
init parameters.- JNDI attributes from
java:comp/env
. - Java System properties (
System.getProperties()
). - OS environment variables.
- A
RandomValuePropertySource
that only has properties inrandom.*
. - Profile-specific application properties outside of your packaged jar (
application-{profile}.properties
and YAML variants) - Profile-specific application properties packaged inside your jar (
application-{profile}.properties
and YAML variants) - Application properties outside of your packaged jar (
application.properties
and YAML variants). - Application properties packaged inside your jar (
application.properties
and YAML variants). @PropertySource
annotations on your@Configuration
classes.- Default properties (specified using
SpringApplication.setDefaultProperties
). - 根目录下的开发工具全局设置属性(当开发工具激活时为
~/.spring-boot-devtools.properties
)。 - 测试中的
@TestPropertySource
注解。 - 测试中的
@SpringBootTest#properties
注解特性。 - 命令行参数。
SPRING_APPLICATION_JSON
中的属性(环境变量或系统属性中的内联JSON嵌入)。ServletConfig
初始化参数。ServletContext
初始化参数。java:comp/env
的JNDI特性。- Java系统属性 (
System.getProperties()
)。 - 操作系统环境变量。
RandomValuePropertySource
只在random.*
中有属性。- jar包之外的指定配置文件的应用属性(
application-{profile}.properties
和YAML变量)。 - jar包之内的指定配置文件的应用属性(
application-{profile}.properties
和YAML变量)。 - jar包之外的应用属性 (
application.properties
和YAML变量)。 - jar包之内的应用属性 (
application.properties
和YAML变量)。 @Configuration
类中的@PropertySource
注解 。- 默认属性(通过
SpringApplication.setDefaultProperties
指定).
To provide a concrete example, suppose you develop a @Component
that uses a name
property:
为了提供一个具体的例子,假设你开发了一个使用name
属性的@Component
:
import org.springframework.stereotype.*
import org.springframework.beans.factory.annotation.*
@Component
public class MyBean {
@Value("${name}")
private String name;
// ...
}
On your application classpath (e.g. inside your jar) you can have an application.properties
that provides a sensible default property value for name
. When running in a new environment, an application.properties
can be provided outside of your jar that overrides the name
; and for one-off testing, you can launch with a specific command line switch (e.g. java -jar app.jar --name="Spring"
).
在你的应用路径中(例如在你的jar内部),你可以使用application.properties
为name
提供一个合理的默认属性值。当在新环境运行时,application.properties
可以在jar外部提供来重写name
;对于一次性测试,你可以通过指定的命令行切换来启动(例如java -jar app.jar --name="Spring"
)。
代码语言:javascript复制The
SPRING_APPLICATION_JSON
properties can be supplied on the command line with an environment variable. For example in a UN*X shell:
$ SPRING_APPLICATION_JSON='{"foo":{"bar":"spam"}}' java -jar myapp.jar
代码语言:javascript复制In this example you will end up with
foo.bar=spam
in the SpringEnvironment
. You can also supply the JSON asspring.application.json
in a System variable:
$ java -Dspring.application.json='{"foo":"bar"}' -jar myapp.jar
or command line argument:
代码语言:javascript复制$ java -jar myapp.jar --spring.application.json='{"foo":"bar"}'
代码语言:javascript复制or as a JNDI variable
java:comp/env/spring.application.json
.
SPRING_APPLICATION_JSON
可以在命令行中通过环境变量提供。例如在UNIX shell中:
$ SPRING_APPLICATION_JSON='{"foo":{"bar":"spam"}}' java -jar myapp.jar
代码语言:javascript复制在这个例子中,Spring的
Environment
中会有foo.bar=spam
。你也可以在系统变量中提供JSON作为spring.application.json
。
$ java -Dspring.application.json='{"foo":"bar"}' -jar myapp.jar
代码语言:javascript复制或命令行参数:
$ java -jar myapp.jar --spring.application.json='{"foo":"bar"}'
或JNDI变量
java:comp/env/spring.application.json
24.1 Configuring random values
The RandomValuePropertySource
is useful for injecting random values (e.g. into secrets or test cases). It can produce integers, longs, uuids or strings, e.g.
当注入随机值时,RandomValuePropertySource
是很有用的(例如,注入秘密或测试用例)。它可以产生integers
,longs
,uuids
或strings
,例如:
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]}
The random.int*
syntax is OPEN value (,max) CLOSE
where the OPEN,CLOSE
are any character and value,max
are integers. If max
is provided then value
is the minimum value and max
is the maximum (exclusive).
random.int*
语法OPEN value (,max) CLOSE
,OPEN,CLOSE
可以是任何字符,value,max
是整数。如果提供了max
,则value
是最小值,max
是最大值(不包含)。
24.2 Accessing command line properties
By default SpringApplication
will convert any command line option arguments (starting with ‘–’, e.g. --server.port=9000
) to a property
and add it to the Spring Environment
. As mentioned above, command line properties always take precedence over other property sources.
默认情况下,SpringApplication
会将任何命令行参数(以--
开头,例如--server.port=9000
)转换成property
并将其添加到Spring的Environment
中。正如前面提到的那样,命令行属性总是优先于其它的配置源。
If you don’t want command line properties to be added to the Environment
you can disable them using SpringApplication.setAddCommandLineProperties(false)
.
如果你想命令行属性添加到Environment
中,你可以使用SpringApplication.setAddCommandLineProperties(false)
禁用它。
24.3 Application property files
SpringApplication
will load properties from application.properties
files in the following locations and add them to the Spring Environment
:
- A
/config
subdirectory of the current directory. - The current directory
- A classpath
/config
package - The classpath root
SpringApplication
会从以下位置的application.properties
文件中加载属性并将它们添加到Spring的Environment
中:
- 当前目录的子目录
/config
- 当前目录
- classpath中的
/config
包 - classpath的根目录
The list is ordered by precedence (properties defined in locations higher in the list override those defined in lower locations).
这个列表是按优先级排序的(在更高位置的属性会重写定义在更低位置的属性)。
You can also use YAML (‘.yml’) files as an alternative to ‘.properties’.
你也可以使用YAML(
.yml
)文件来代替.properties
文件。
If you don’t like application.properties
as the configuration file name you can switch to another by specifying a spring.config.name
environment property. You can also refer to an explicit location using the spring.config.location
environment property (comma-separated list of directory locations, or file paths).
如果你不喜欢用application.properties
作为配置文件的名字,你可以通过指定spring.config.name
环境属性来来改变配置文件的名字。你也可以使用spring.config.location
环境属性来引用一个显式的位置(目录位置或文件路径以逗号分隔)。
$ java -jar myproject.jar --spring.config.name=myproject
or
代码语言:javascript复制$ java -jar myproject.jar --spring.config.location=classpath:/default.properties,classpath:/override.properties
spring.config.name
andspring.config.location
are used very early to determine which files have to be loaded so they have to be defined as an environment property (typically OS env, system property or command line argument).
spring.config.name
和spring.config.location
可以在早期用来决定加载哪一个文件,因此必须被定义为环境属性(通常是操作系统环境,系统属性或命令行参数)。
If spring.config.location
contains directories (as opposed to files) they should end in /
(and will be appended with the names generated from spring.config.name
before being loaded, including profile-specific file names). Files specified in spring.config.location
are used as-is, with no support for profile-specific variants, and will be overridden by any profile-specific properties.
如果spring.config.location
包含目录(相对于文件而言),它们应该以/
结尾(在加载之前,在后面添加上从spring.config.name
中产生的名字,包括指定配置文件的名字)。在spring.config.location
中指定的文件按原样使用,不支持指定配置文件变量,将会被任何指定配置文件的属性覆盖。
The default search path classpath:,classpath:/config,file:,file:config/
is always used, irrespective of the value of spring.config.location
. This search path is ordered from lowest to highest precedence (file:config/
wins). If you do specify your own locations, they take precedence over all of the default locations and use the same lowest to highest precedence ordering. In that way you can set up default values for your application in application.properties
(or whatever other basename you choose with spring.config.name
) and override it at runtime with a different file, keeping the defaults.
默认搜索路径一直用classpath:,classpath:/config,file:,file:config/
,不管spring.config.location
中的值。搜索路径按从低到高排序(file:config/
最高)。如果你指定了自己的位置,它们优先于所有的默认位置并使用同样的从低到高的顺序。这样你可以在application.properties
中为你的应用设置默认值(或你可以选择spring.config.name
的其它生成文件基本名),在运行时用其它的文件覆盖它,同时保留默认值。
If you use environment variables rather than system properties, most operating systems disallow period-separated key names, but you can use underscores instead (e.g.
SPRING_CONFIG_NAME
instead ofspring.config.name
).如果你使用环境变量而不是系统属性,大多数操作系统不允许句号分隔的关键字,但你可以用下划线代替(例如,
SPRING_CONFIG_NAME
代替spring.config.name
)。 If you are running in a container then JNDI properties (injava:comp/env
) or servlet context initialization parameters can be used instead of, or as well as, environment variables or system properties.如果你在容器中运行,那么JNDI属性(在
java:comp/env
中)或servlet上下文初始化参数也可以用来代替环境变量或系统属性。
24.4 Profile-specific properties
In addition to application.properties
files, profile-specific properties can also be defined using the naming convention application-{profile}.properties
. The Environment
has a set of default profiles (by default [default]
) which are used if no active profiles are set (i.e. if no profiles are explicitly activated then properties from application-default.properties
are loaded).
除了application.properties
文件之外,特定的profile属性也可以使用命名规范application-{profile}.properties
来定义。Environment
有一系列默认配置文件(默认为[default]
),如果没有设置激活的配置文件,会使用默认的配置文件(例如,如果没有激活显式的配置文件,则会加载application-default.properties
中的属性)。
Profile-specific properties are loaded from the same locations as standard application.properties
, with profile-specific files always overriding the non-specific ones irrespective of whether the profile-specific files are inside or outside your packaged jar.
特定的profile属性会从相同位置加载application.properties
,特定的profile文件总是覆盖非特定的配置文件,无论特定profile文件在你打包的jar内部还是外部。
If several profiles are specified, a last wins strategy applies. For example, profiles specified by the spring.profiles.active
property are added after those configured via the SpringApplication
API and therefore take precedence.
如果指定了几个配置文件,将会应用最后一个。例如,spring.profiles.active
属性指定的配置文件在那些配置的文件之后通过SpringApplication
API添加,因此优先级更高。
If you have specified any files in
spring.config.location
, profile-specific variants of those files will not be considered. Use directories inspring.config.location
if you also want to also use profile-specific properties.如果你在
spring.config.location
中指定了任何文件,那些文件的特定profile版本将不会被考虑。如果你也想使用特定的profile属性,在spring.config.location
中使用目录。
24.5 Placeholders in properties
The values in application.properties
are filtered through the existing Environment
when they are used so you can refer back to previously defined values (e.g. from System properties).
当使用application.properties
中的值时,会通过现有的Environment
进行过滤,因此你可以参考前面定义的值(例如从系统属性中)。
app.name=MyApp
app.description=${app.name} is a Spring Boot application
You can also use this technique to create ‘short’ variants of existing Spring Boot properties. See the Section 70.4, “Use ‘short’ command line arguments” how-to for details.
你也可以使用这个技术来创建现有的Spring Boot属性的
short
版本。怎样使用的更多细节请看70.4小节,“Use ‘short’ command line arguments”。
24.6 Using YAML instead of Properties
YAML is a superset of JSON, and as such is a very convenient format for specifying hierarchical configuration data. The SpringApplication
class will automatically support YAML as an alternative to properties whenever you have the SnakeYAML library on your classpath.
YAML是JSON的超集,它可以用一种非常方便的形式来指定分层配置数据。当你的类路径有SnakeYAML库时,SpringApplication
类自动支持YAML作为properties的一个替代品。
If you use ‘Starters’ SnakeYAML will be automatically provided via
spring-boot-starter
.如果你使用‘Starters’,SnakeYAML将由
spring-boot-starter
自动提供。
24.6.1 Loading YAML
Spring Framework provides two convenient classes that can be used to load YAML documents. The YamlPropertiesFactoryBean
will load YAML as Properties
and the YamlMapFactoryBean
will load YAML as a Map
.
Spring框架提供了两个类用来方便的加载YAML文档。YamlPropertiesFactoryBean
将加载YAML作为Properties
,YamlMapFactoryBean
将加载YAML作为Map
。
For example, the following YAML document:
例如,下面的YAML文档:
代码语言:javascript复制environments:
dev:
url: http://dev.bar.com
name: Developer Setup
prod:
url: http://foo.bar.com
name: My Cool App
Would be transformed into these properties:
将被转换成这些属性:
代码语言:javascript复制environments.dev.url=http://dev.bar.com
environments.dev.name=Developer Setup
environments.prod.url=http://foo.bar.com
environments.prod.name=My Cool App
YAML lists are represented as property keys with [index]
dereferencers, for example this YAML:
YAML列表通过[index]
解引用表示为属性的key,例如这个YAML:
my:
servers:
- dev.bar.com
- foo.bar.com
Would be transformed into these properties:
将被转换成这些属性:
代码语言:javascript复制my.servers[0]=dev.bar.com
my.servers[1]=foo.bar.com
To bind to properties like that using the Spring DataBinder
utilities (which is what @ConfigurationProperties
does) you need to have a property in the target bean of type java.util.List
(or Set
) and you either need to provide a setter
, or initialize it with a mutable value, e.g. this will bind to the properties above:
为了像使用Spring的DataBinder
一样(@ConfigurationProperties
的功能)绑定这些属性,你需要在类型为java.util.List
(或Set
)的目标bean中有属性,你需要提供一个setter
或用一个可变的值来对它初始化,例如,绑定上面的属性值:
@ConfigurationProperties(prefix="my")
public class Config {
private List<String> servers = new ArrayList<String>();
public List<String> getServers() {
return this.servers;
}
}
24.6.2 Exposing YAML as properties in the Spring Environment
The YamlPropertySourceLoader
class can be used to expose YAML as a PropertySource
in the Spring Environment
. This allows you to use the familiar @Value
annotation with placeholders syntax to access YAML properties.
YamlPropertySourceLoader
类可以在Spring的Environment
中将YAML作为PropertySource
。这允许你使用熟悉的@Value
注解和占位符语法来访问YAML属性。
24.6.3 Multi-profile YAML documents
You can specify multiple profile-specific YAML documents in a single file by using a spring.profiles
key to indicate when the document applies. For example:
你可以在单个文件中指定多个特定profile的YAML文档,当应用文档时,通过spring.profiles
关键字来表明使用哪个文档。例如:
server:
address: 192.168.1.100
---
spring:
profiles: development
server:
address: 127.0.0.1
---
spring:
profiles: production
server:
address: 192.168.1.120
In the example above, the server.address
property will be 127.0.0.1
if the development
profile is active. If the development
and production
profiles are not enabled, then the value for the property will be 192.168.1.100
.
在上面的例子中,如果development
profile被激活,server.address
的值为127.0.0.1
。如果development
和production
profile不可用,server.address
的值为192.168.1.100
。
The default profiles are activated if none are explicitly active when the application context starts. So in this YAML we set a value for security.user.password
that is only available in the “default” profile:
当应用上下文启动时,如果没有显式的激活profile,则激活默认的profile。因此在这个YAML文件中我们仅在”default” profile中设置了security.user.password
。
server:
port: 8000
---
spring:
profiles: default
security:
user:
password: weak
whereas in this example, the password is always set because it isn’t attached to any profile, and it would have to be explicitly reset in all other profiles as necessary:
在这个例子中,密码总是设置的,因为它没有添加到如何profile中,必要时我们必须在其它的profile中显式的对它重新设置:
代码语言:javascript复制server:
port: 8000
security:
user:
password: weak
Spring profiles designated using the “spring.profiles” element may optionally be negated using the !
character. If both negated and non-negated profiles are specified for a single document, at least one non-negated profile must match and no negated profiles may match.
Spring profiles被设计为使用”spring.profiles”元素可以选择性的用!
字符进行否定。如果否定的和非否定的profile指向一个单独的文档,必须至少匹配一个非否定的profile,可能没有否定的profile进行匹配。
24.6.4 YAML shortcomings
YAML files can’t be loaded via the @PropertySource
annotation. So in the case that you need to load values that way, you need to use a properties file.
YAML文件不能通过@PropertySource
注解进行加载。因此在这种情况下如果你需要加载值,你需要使用属性文件。
24.6.5 Merging YAML lists
As we have seen above, any YAML content is ultimately transformed to properties. That process may be counter intuitive when overriding “list” properties via a profile.
正如我们上面看到的,任何YAML内容最终都要转换成属性。当通过profile重写“list“属性时,这个过程可能有违直觉。
For example, assume a MyPojo
object with name
and description
attributes that are null by default. Let’s expose a list of MyPojo
from FooProperties
:
例如,假设MyPojo
对象的name
和description
属性默认情况下为空。从FooProperties
公开一个MyPojo
列表:
@ConfigurationProperties("foo")
public class FooProperties {
private final List<MyPojo> list = new ArrayList<>();
public List<MyPojo> getList() {
return this.list;
}
}
Consider the following configuration:
考虑下面的配置:
代码语言:javascript复制foo:
list:
- name: my name
description: my description
---
spring:
profiles: dev
foo:
list:
- name: my another name
If the dev
profile isn’t active, FooProperties.list
will contain one MyPojo
entry as defined above. If the dev
profile is enabled however, the list
will still only contain one entry (with name “my another name” and description null). This configuration will not add a second MyPojo
instance to the list
, and it won’t merge the items.
如果dev
profile没有激活,FooProperties.list
将包含一个上面定义的MyPojo
输入。然而如果dev
profile可用,lists
仍只包含一个输入(name为“my another name”,description为空)。这个配置将不能添加第二个MyPojo
到list
中,并且它将不能合并这些项。
When a collection is specified in multiple profiles, the one with highest priority is used (and only that one):
当在多个profiles中指定一个集合时,将会使用最高优先级的那个集合(唯一的哪个):
代码语言:javascript复制foo:
list:
- name: my name
description: my description
- name: another name
description: another description
---
spring:
profiles: dev
foo:
list:
- name: my another name
In the example above, considering that the dev
profile is active, FooProperties.list
will contain one MyPojo
entry (with name “my another name” and description null).
在上面的例子中,假设dev
profile被激活,FooProperties.list
将包含一个MyPojo
输入(name为“my another name”,description为空)。
24.7 Type-safe Configuration Properties
Using the @Value("${property}")
annotation to inject configuration properties can sometimes be cumbersome, especially if you are working with multiple properties or your data is hierarchical in nature. Spring Boot provides an alternative method of working with properties that allows strongly typed beans to govern and validate the configuration of your application. For example:
使用@Value("${property}")
注解来注入配置信息有时会很麻烦,尤其是你正在使用多属性或你的数据本质上是分层的情况下。Spring Boot提供了一种处理属性的可替代方法,允许强类型的beans管理和验证你的应用的配置。例如:
@ConfigurationProperties(prefix="connection")
public class ConnectionProperties {
private String username;
private InetAddress remoteAddress;
// ... getters and setters
}
The getters and setters are advisable, since binding is via standard Java Beans property descriptors, just like in Spring MVC. They are mandatory for immutable types or those that are directly coercible from
String
. As long as they are initialized, maps, collections, and arrays need a getter but not necessarily a setter since they can be mutated by the binder. If there is a setter, Maps, collections, and arrays can be created. Maps and collections can be expanded with only a getter, whereas arrays require a setter. Nested POJO properties can also be created (so a setter is not mandatory) if they have a default constructor, or a constructor accepting a single value that can be coerced fromString
. Some people use Project Lombok to add getters and setters automatically.建议添加getters和setters,绑定是通过标准的Java Beans属性描述符,像在Spring MVC中一样。对于不可变类型或那些从
String
中可直接强制转换的类型,它们是强制性的。只要它们被初始化,maps,集合或数组需要getter方法,但不需要setter方法因为通过绑定起它们可以直接变化。如果有setter,可以创建Maps,集合和数组。Maps和集合可以通过getter扩展,数组扩展需要setter。如果它们有默认的构造函数,或构造函数接收可以从String
类型强制转换的值,嵌入的POJO属性也可以创建(因此setter不是强制性的)。一些人使用Lombok项目来自动添加getter和setter。 See also the differences between@Value
and@ConfigurationProperties
.请看
@Value
和@ConfigurationProperties
之间的不同。
You also need to list the properties classes to register in the @EnableConfigurationProperties
annotation:
你也需要在@EnableConfigurationProperties
注解中列出要注册的属性类:
@Configuration
@EnableConfigurationProperties(ConnectionProperties.class)
public class MyConfiguration {
}
When
@ConfigurationProperties
bean is registered that way, the bean will have a conventional name:<prefix>-<fqn>
, where<prefix>
is the environment key prefix specified in the@ConfigurationProperties
annotation and<fqn>
the fully qualified name of the bean. If the annotation does not provide any prefix, only the fully qualified name of the bean is used. The bean name in the example above will beconnection-com.example.ConnectionProperties
, assuming thatConnectionProperties
sits in thecom.example
package.当
@ConfigurationProperties
以那种方式注册时,这个bean将有一个常规的名字:<prefix>-<fqn>
,<prefix>
是在@ConfigurationProperties
注解中指定的环境关键字的前缀,<fqn>
是bean的完整合格的名字。如果注解没有提供任何前缀,则只用bean的完整合格的名字。 在上面的例子中bean名字是connection-com.example.ConnectionProperties
,假设ConnectionProperties
在com.example
包中。
Even if the configuration above will create a regular bean for ConnectionProperties
, we recommend that @ConfigurationProperties
only deal with the environment and in particular does not inject other beans from the context. Having said that, The @EnableConfigurationProperties
annotation is also automatically applied to your project so that any existing bean annotated with @ConfigurationProperties
will be configured from the Environment
properties. You could shortcut MyConfiguration
above by making sure ConnectionProperties
is a already a bean:
即使上面的配置会为ConnectionProperties
创建一个正规的bean,我们建议@ConfigurationProperties
只处理环境,特别是不从上下文中注入其它的beans。已经说过,为了任何带有@ConfigurationProperties
注解的bean可以根据Environment
属性进行配置,@EnableConfigurationProperties
注解也自动应用到你的工程中。确保ConnectionProperties
已经是一个bean,你可以简写上面的MyConfiguration
:
@Component
@ConfigurationProperties(prefix="connection")
public class ConnectionProperties {
// ... getters and setters
}
This style of configuration works particularly well with the SpringApplication
external YAML configuration:
这种风格的配置在SpringApplication
的外部化YAML配置中工作的尤其好:
# application.yml
connection:
username: admin
remoteAddress: 192.168.1.1
# additional configuration as required
To work with @ConfigurationProperties
beans you can just inject them in the same way as any other bean.
为了同@ConfigurationProperties
beans一起工作,你可以像任何其它bean一样以相同的方式注入它们:
@Service
public class MyService {
private final ConnectionProperties connection;
@Autowired
public MyService(ConnectionProperties connection) {
this.connection = connection;
}
//...
@PostConstruct
public void openConnection() {
Server server = new Server();
this.connection.configure(server);
}
}
Using
@ConfigurationProperties
also allows you to generate meta-data files that can be used by IDEs. See the Appendix B, Configuration meta-data appendix for details.使用
@ConfigurationProperties
也允许你生成IDEs可以使用的元数据文件。更多细节请看附录B,配置元数据附录。
24.7.1 Third-party configuration
As well as using @ConfigurationProperties
to annotate a class, you can also use it on public @Bean
methods. This can be particularly useful when you want to bind properties to third-party components that are outside of your control.
To configure a bean from the Environment properties, add @ConfigurationProperties to its bean registration:
也可以使用@ConfigurationProperties
来注解一个类,你也可以在公有的@Bean
方法上使用它。当你想绑定属性到你控制之外的第三方组件上时尤其有用。
@ConfigurationProperties(prefix = "foo")
@Bean
public FooComponent fooComponent() {
...
}
Any property defined with the foo
prefix will be mapped onto that FooComponent
bean in a similar manner as the ConnectionProperties
example above.
任何定义的带有foo
前缀的属性都将以类似于上面的ConnectionProperties
例子中的方式映射到FooComponent
bean中。
24.7.2 Relaxed binding
Spring Boot uses some relaxed rules for binding Environment
properties to @ConfigurationProperties
beans, so there doesn’t need to be an exact match between the Environment
property name and the bean property name. Common examples where this is useful include dashed separated (e.g. context-path
binds to contextPath
), and capitalized (e.g. PORT
binds to port
) environment properties.
Spring Boot使用一些松散的规则将Environment
属性绑定到@ConfigurationProperties
beans上,因此不需要在Environment
属性名和bean属性名之间进行确切的匹配。常见的有用例子包括破折号分隔(例如,context-path绑定到contextPath),大小写(例如PORT
绑定到port
,)环境属性。
For example, given the following @ConfigurationProperties
class:
例如,给定下面的@ConfigurationProperties
类:
@ConfigurationProperties(prefix="person")
public class OwnerProperties {
private String firstName;
public String getFirstName() {
return this.firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
}
The following properties names can all be used:
下面的属性名都可以使用:
Table 24.1. relaxed binding
Property | Note |
---|---|
person.firstName | Standard camel case syntax. |
person.first-name | Dashed notation, recommended for use in .properties and .yml files. |
person.first_name | Underscore notation, alternative format for use in .properties and .yml files. |
PERSON_FIRST_NAME | Upper case format. Recommended when using a system environment variables. |
表24.1. 松散绑定
Property | Note |
---|---|
person.firstName | 标准的驼峰写法 |
person.first-name | 破折号注解,建议在.properties和.yml文件中使用 |
person.first_name | 下划线注解,.properties和.yml文件中的可替代写法 |
PERSON_FIRST_NAME | 大写形式。当使用系统变量时推荐 |
24.7.3 Properties conversion
Spring will attempt to coerce the external application properties to the right type when it binds to the @ConfigurationProperties
beans. If you need custom type conversion you can provide a ConversionService
bean (with bean id conversionService) or custom property editors (via a CustomEditorConfigurer
bean) or custom Converters
(with bean definitions annotated as @ConfigurationPropertiesBinding
).
当Spring绑定属性到@ConfigurationProperties
beans时,它将试图将外部的应用属性强制转换成正确的类型。如果你需要定制类型转换你可以提供一个ConversionService
bean(bean id为conversionService
),或定制属性编辑器(通过CustomEditorConfigurer
bean),或定制Converters
(带有@ConfigurationPropertiesBinding
注解的bean定义)。
As this bean is requested very early during the application lifecycle, make sure to limit the dependencies that your
ConversionService
is using. Typically, any dependency that you require may not be fully initialized at creation time. You may want to rename your customConversionService
if it’s not required for configuration keys coercion and only rely on custom converters qualified with@ConfigurationPropertiesBindings
.bean要求在应用生命周期中的早期,要确保限制
ConversionService
使用的依赖。通常,任何你要求的依赖可能在创建时不是完整初始化的。如果你定制的ConversionService
不要求配置关键字强制转换,你可能想重新命名你定制的ConversionService
,并且只依赖满足@ConfigurationPropertiesBindings
的定制转换器。
24.7.4 @ConfigurationProperties Validation
Spring Boot will attempt to validate external configuration, by default using JSR-303 (if it is on the classpath). You can simply add JSR-303 javax.validation
constraint annotations to your @ConfigurationProperties
class:
Spring Boot会试图验证外部化配置,默认使用JSR-303(如果它在classpath中)。你可以简单的添加JSR-303 javax.validation
约束注解到你的@ConfigurationProperties
类中:
@ConfigurationProperties(prefix="connection")
public class ConnectionProperties {
@NotNull
private InetAddress remoteAddress;
// ... getters and setters
}
In order to validate values of nested properties, you must annotate the associated field as @Valid
to trigger its validation. For example, building upon the above ConnectionProperties
example:
为了验证嵌入的属性值,你必须注解相关的字段作为@Valid
来触发它的校验。例如,在上面的ConnectionProperties
例子上构建:
@ConfigurationProperties(prefix="connection")
public class ConnectionProperties {
@NotNull
@Valid
private RemoteAddress remoteAddress;
// ... getters and setters
public static class RemoteAddress {
@NotEmpty
public String hostname;
// ... getters and setters
}
}
You can also add a custom Spring Validator
by creating a bean definition called configurationPropertiesValidator
. The @Bean
method should be declared static. The configuration properties validator is created very early in the application’s lifecycle and declaring the @Bean
method as static allows the bean to be created without having to instantiate the @Configuration
class. This avoids any problems that may be caused by early instantiation. There is a property validation sample so you can see how to set things up.
通过创建一个称为configurationPropertiesValidator
的bean定义,你也可以添加定制的Spring Validator
。@Bean
方法应该声明静态的。配置属性验证器在应用生命周期的早期创建,声明@Bean
方法为静态方法,允许不必实例化@Configuration
类就创建bean。这避免了任何早期实例化可能引起的问题。这儿有一个属性验证的例子因此你可以看一下怎样设置它。
The
spring-boot-actuator
module includes an endpoint that exposes all@ConfigurationProperties
beans. Simply point your web browser to/configprops
or use the equivalent JMX endpoint. See the Production ready features. section for details.
spring-boot-actuator
模块包含一个端点,这个端点将公开所有的@ConfigurationProperties
beans。简单的将你的web浏览器指向/configprops
或用等价的JMX端点。更多细节请看产品级功能。
24.7.5 @ConfigurationProperties vs. @Value
@Value
is a core container feature and it does not provide the same features as type-safe Configuration Properties. The table below summarizes the features that are supported by @ConfigurationProperties
and @Value
:
@Value
是一种核心的容器功能,它不能作为类型安全配置属性提供同样的功能。下面的表中总结了@ConfigurationProperties
和@Value
支持的功能:
Feature | @ConfigurationProperties | @Value |
---|---|---|
Relaxed binding | Yes | No |
Meta-data support | Yes | No |
SpEL evaluation | No | Yes |
功能 | @ConfigurationProperties | @Value |
---|---|---|
松散绑定 | Yes | No |
元数据支持 | Yes | No |
SpEL评估 | No | Yes |
If you define a set of configuration keys for your own components, we recommend you to group them in a POJO annotated with @ConfigurationProperties
. Please also be aware that since @Value
does not support relaxed binding, it isn’t a great candidate if you need to provide the value using environment variables.
如果你为自己的组件定义了一些配置关键字,我们建议你将它们分组到带有@ConfigurationProperties
注解的POJO中。也请注意@Value
不支持松散绑定,如果你需要用环境变量提供值,它不是一个好的选择。
Finally, while you can write a SpEL expression in @Value
, such expressions are not processed from Application property files.
最后,虽然你可以在@Value
中写表达式,但这种表达式不能从应用属性文件中处理。