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
@Valueannotation, accessed via Spring’sEnvironmentabstraction or bound to structured objects via@ConfigurationProperties.Spring Boot uses a very particular
PropertySourceorder that is designed to allow sensible overriding of values, properties are considered in the following order:
- Command line arguments.
- Properties from
SPRING_APPLICATION_JSON(inline JSON embedded in an environment variable or system property)- JNDI attributes from
java:comp/env.- Java System properties (
System.getProperties()).- OS environment variables.
- A
RandomValuePropertySourcethat only has properties inrandom.*.- Profile-specific application properties outside of your packaged jar (
application-{profile}.propertiesand YAML variants)- Profile-specific application properties packaged inside your jar (
application-{profile}.propertiesand YAML variants)- Application properties outside of your packaged jar (
application.propertiesand YAML variants).- Application properties packaged inside your jar (
application.propertiesand YAML variants).@PropertySourceannotations on your@Configurationclasses.- Default properties (specified using
SpringApplication.setDefaultProperties).To provide a concrete example, suppose you develop a
@Componentthat uses anameproperty: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.propertiesthat provides a sensible default property value forname. When running in a new environment, anapplication.propertiescan be provided outside of your jar that overrides thename; and for one-off testing, you can launch with a specific command line switch (e.g.java -jar app.jar --name="Spring").
The
SPRING_APPLICATION_JSONproperties 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.jarIn this example you will end up with
foo.bar=spamin the SpringEnvironment. You can also supply the JSON asspring.application.jsonin a System variable:$ java -Dspring.application.json='{"foo":"bar"}' -jar myapp.jaror command line argument:
$ java -jar myapp.jar --spring.application.json='{"foo":"bar"}'or as a JNDI variable
java:comp/env/spring.application.json.24.1 Configuring random values
The
RandomValuePropertySourceis useful for injecting random values (e.g. into secrets or test cases). It can produce integers, longs or strings, e.g.my.secret=${random.value} my.number=${random.int} my.bignumber=${random.long} my.number.less.than.ten=${random.int(10)} my.number.in.range=${random.int[1024,65536]}The
random.int*syntax isOPEN value (,max) CLOSEwhere theOPEN,CLOSEare any character andvalue,maxare integers. Ifmaxis provided thenvalueis the minimum value andmaxis the maximum (exclusive).24.2 Accessing command line properties
By default
SpringApplicationwill convert any command line option arguments (starting with ‘--’, e.g.--server.port=9000) to apropertyand add it to the SpringEnvironment. As mentioned above, command line properties always take precedence over other property sources.If you don’t want command line properties to be added to the
Environmentyou can disable them usingSpringApplication.setAddCommandLineProperties(false).24.3 Application property files
SpringApplicationwill load properties fromapplication.propertiesfiles in the following locations and add them to the SpringEnvironment:
- A
/configsubdirectory of the current directory.- The current directory
- A classpath
/configpackage- The classpath root
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'.
If you don’t like
application.propertiesas the configuration file name you can switch to another by specifying aspring.config.nameenvironment property. You can also refer to an explicit location using thespring.config.locationenvironment property (comma-separated list of directory locations, or file paths).$ java -jar myproject.jar --spring.config.name=myprojector
$ java -jar myproject.jar --spring.config.location=classpath:/default.properties,classpath:/override.properties
spring.config.nameandspring.config.locationare 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).If
spring.config.locationcontains directories (as opposed to files) they should end in/(and will be appended with the names generated fromspring.config.namebefore being loaded, including profile-specific file names). Files specified inspring.config.locationare used as-is, with no support for profile-specific variants, and will be overridden by any profile-specific properties.The default search path
classpath:,classpath:/config,file:,file:config/is always used, irrespective of the value ofspring.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 inapplication.properties(or whatever other basename you choose withspring.config.name) and override it at runtime with a different file, keeping the defaults.
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_NAMEinstead ofspring.config.name).
If you are running in a container then JNDI properties (in
java:comp/env) or servlet context initialization parameters can be used instead of, or as well as, environment variables or system properties.24.4 Profile-specific properties
In addition to
application.propertiesfiles, profile-specific properties can also be defined using the naming conventionapplication-{profile}.properties. TheEnvironmenthas 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 fromapplication-default.propertiesare loaded).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.If several profiles are specified, a last wins strategy applies. For example, profiles specified by the
spring.profiles.activeproperty are added after those configured via theSpringApplicationAPI and therefore take precedence.
If you have specified any files in
spring.config.location, profile-specific variants of those files will not be considered. Use directories in`spring.config.location` if you also want to also use profile-specific properties.24.5 Placeholders in properties
The values in
application.propertiesare filtered through the existingEnvironmentwhen they are used so you can refer back to previously defined values (e.g. from System properties).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 69.3, “Use ‘short’ command line arguments”how-to for details.
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
SpringApplicationclass will automatically support YAML as an alternative to properties whenever you have the SnakeYAML library on your classpath.
If you use ‘starter POMs’ SnakeYAML will be automatically provided via
spring-boot-starter.24.6.1 Loading YAML
Spring Framework provides two convenient classes that can be used to load YAML documents. The
YamlPropertiesFactoryBeanwill load YAML asPropertiesand theYamlMapFactoryBeanwill load YAML as aMap.For example, the following YAML document:
environments: dev: url: http://dev.bar.com name: Developer Setup prod: url: http://foo.bar.com name: My Cool AppWould be transformed into these properties:
environments.dev.url=http://dev.bar.com environments.dev.name=Developer Setup environments.prod.url=http://foo.bar.com environments.prod.name=My Cool AppYAML lists are represented as property keys with
[index]dereferencers, for example this YAML:my: servers: - dev.bar.com - foo.bar.comWould be transformed into these properties:
my.servers[0]=dev.bar.com my.servers[1]=foo.bar.comTo bind to properties like that using the Spring
DataBinderutilities (which is what@ConfigurationPropertiesdoes) you need to have a property in the target bean of typejava.util.List(orSet) and you either need to provide a setter, or initialize it with a mutable value, e.g. this will bind to the properties above@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
YamlPropertySourceLoaderclass can be used to expose YAML as aPropertySourcein the SpringEnvironment. This allows you to use the familiar@Valueannotation with placeholders syntax to access YAML properties.24.6.3 Multi-profile YAML documents
You can specify multiple profile-specific YAML documents in a single file by using a
spring.profileskey to indicate when the document applies. For example:server: address: 192.168.1.100 --- spring: profiles: development server: address: 127.0.0.1 --- spring: profiles: production server: address: 192.168.1.120In the example above, the
server.addressproperty will be127.0.0.1if thedevelopmentprofile is active. If thedevelopmentandproductionprofiles are notenabled, then the value for the property will be192.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.passwordthat isonly available in the "default" profile:server: port: 8000 --- spring: profiles: default security: user: password: weakwhereas 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:
server: port: 8000 security: user: password: weak24.6.4 YAML shortcomings
YAML files can’t be loaded via the
@PropertySourceannotation. So in the case that you need to load values that way, you need to use a properties file.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:@Component @ConfigurationProperties(prefix="connection") public class ConnectionSettings { 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 from String. Some people use Project Lombok to add getters and setters automatically.
Contrary to
@Value, SpEL expressions are not evaluated prior to injecting a value in the relevant@ConfigurationPropertiesbean.The
@EnableConfigurationPropertiesannotation is automatically applied to your project so that any beans annotated with@ConfigurationPropertieswill be configured from theEnvironmentproperties. This style of configuration works particularly well with theSpringApplicationexternal YAML configuration:# application.yml connection: username: admin remoteAddress: 192.168.1.1 # additional configuration as requiredTo work with
@ConfigurationPropertiesbeans you can just inject them in the same way as any other bean.@Service public class MyService { @Autowired private ConnectionSettings connection; //... @PostConstruct public void openConnection() { Server server = new Server(); this.connection.configure(server); } }It is also possible to shortcut the registration of
@ConfigurationPropertiesbean definitions by simply listing the properties classes directly in the@EnableConfigurationPropertiesannotation:@Configuration @EnableConfigurationProperties(ConnectionSettings.class) public class MyConfiguration { }
Using
@ConfigurationPropertiesalso allows you to generate meta-data files that can be used by IDEs. See the Appendix B, Configuration meta-dataappendix for details.24.7.1 Third-party configuration
As well as using
@ConfigurationPropertiesto annotate a class, you can also use it on@Beanmethods. 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
Environmentproperties, add@ConfigurationPropertiesto its bean registration:@ConfigurationProperties(prefix = "foo") @Bean public FooComponent fooComponent() { ... }Any property defined with the
fooprefix will be mapped onto thatFooComponentbean in a similar manner as theConnectionSettingsexample above.24.7.2 Relaxed binding
Spring Boot uses some relaxed rules for binding
Environmentproperties to@ConfigurationPropertiesbeans, so there doesn’t need to be an exact match between theEnvironmentproperty name and the bean property name. Common examples where this is useful include dashed separated (e.g.context-pathbinds tocontextPath), and capitalized (e.g.PORTbinds toport) environment properties.For example, given the following
@ConfigurationPropertiesclass:@Component @ConfigurationProperties(prefix="person") public class ConnectionSettings { 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.firstNameStandard camel case syntax.
person.first-nameDashed notation, recommended for use in
.propertiesand.ymlfiles.
PERSON_FIRST_NAMEUpper case format. Recommended when using a system environment variables.
24.7.3 Properties conversion
Spring will attempt to coerce the external application properties to the right type when it binds to the
@ConfigurationPropertiesbeans. If you need custom type conversion you can provide aConversionServicebean (with bean idconversionService) or custom property editors (via aCustomEditorConfigurerbean) or customConverters(with bean definitions annotated as@ConfigurationPropertiesBinding).
As this bean is requested very early during the application lifecycle, make sure to limit the dependencies that your
ConversionServiceis using. Typically, any dependency that you require may not be fully initialized at creation time. You may want to rename your customConversionServiceif it’s not required for configuration keys coercion and only rely on custom converters qualified with@ConfigurationPropertiesBinding.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.validationconstraint annotations to your@ConfigurationPropertiesclass:@Component @ConfigurationProperties(prefix="connection") public class ConnectionSettings { @NotNull private InetAddress remoteAddress; // ... getters and setters }In order to validate values of nested properties, you must annotate the associated field as
@Validto trigger its validation. For example, building upon the aboveConnectionSettingsexample:@Component @ConfigurationProperties(prefix="connection") public class ConnectionSettings { @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
Validatorby creating a bean definition calledconfigurationPropertiesValidator. There is a Validation sample so you can see how to set things up.
The
spring-boot-actuatormodule includes an endpoint that exposes all@ConfigurationPropertiesbeans. Simply point your web browser to/configpropsor use the equivalent JMX endpoint. See the Production ready features. section for details.
How to access a value defined in the application.properties file in Spring Boot ( Externalized Conf)
本文介绍如何使用 Spring Boot 进行配置外部化,包括属性文件、环境变量及命令行参数等多种方式,并探讨 YAML 文件的使用及类型安全配置属性。
![[Tip]](https://i-blog.csdnimg.cn/blog_migrate/27a1e7ae236c2304362f9ac23d3571d6.png)
![[Note]](https://i-blog.csdnimg.cn/blog_migrate/3f2dcdc638ae1627d75a9b79b06aab85.png)
![[Warning]](https://i-blog.csdnimg.cn/blog_migrate/3362acb60c20d4ae899be5a2257d7a11.png)

被折叠的 条评论
为什么被折叠?



