持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第08天,点击查看活动详情
Spring Boot 中的一个显著特性就是对外部化配置(externalized configuration)的支持。 今天我们将围绕两个问题来学习下 Spring / Spring Boot 中如何使用外部配置文件的。 首先,我们先来了解下如何向 Spring 框架中注册一个配置文件和如何使用配置文件中的值。 然后,我们会一块学习下 Spring Boot 是如何简化和增强 Spring 框架中对外部配置文件的注册和使用的。 好了,废话不多说,让我们直奔主题吧。
01-注册 Property 文件
使用@PropertySource注解,通过指定属性文件路径,Spring 框架会自动加载属性文件中的内容,并将加载到的属性添加到 Environment 中。
这就是 Spring 框架提供的机制。其使用示例如下:
@Configuration
@PropertySource("classpath:foo.properties")
public class SomeConfig {
//...
}
注:在指定属性文件路径时,支持使用现有的属性值作为占位符,例如:
// 如果在 foo.properties 中定义了 var=foo,或者运行时传递了参数 --var=foo
// 那么, ${var:default}.properties 就为 foo.properties,否则,为 default.properties
@PropertySource("classpath:foo.properties")
@PropertySource("classpath:properties/${var:default}.properties")
Java 8 及以上版本支持上述写法来引入多个属性文件。如果使用 Java 7 及以下版本,可以使用@PropertyResources来同时引入多个属性文件。
下述为 Java 7 及以下版本的等价写法:
@PropertySources({
@PropertySource("classpath:properties/foo.properties"),
@PropertySource("classpath:properties/${var:default}.properties")
})
02-使用 Property
两种方式:
@Value注解,其 value 值可以是属性占位符${...}或者 SpEL 表达式#{...}。- 实现
EnvironmentAware接口获得 Environment 对象,然后调用其 getProperty 方法,获得注册在 Environment 中的属性值。
03-Spring Boot 中对 Property 的高级特性
默认情况下,Spring Boot 启动时会自动加载如下路径中的 application.properties 和 application.yaml 属性文件:
- optional:classpath:/;optional:classpath:/config/
- optional:file:./;optional:file:./config/;optional:file:./config/*/
注意:optional 意味可选地、非必须的,若没有 optional,Spring Boot 在找不到文件时,会抛 ConfigDataLocationNotFoundException 异常; 以";"分割的多个文件或路径同属一个 group; 当值为路径时,必须以"/"或"/"结尾; ""为通配符,仅用在值为路径时,且只能出现一次,且只能以"*/"结尾方式出现
加载的属性文件会被添加到 Environment 中的 PropertySources 中。
使用spring.config.location会替换掉默认的查找路径,如果想加载额外的查找路径,可以使用spring.config.additional-location。
例如,如果不设置spring.config.location,而设置spring.config.additional-location=optional:classpath:/custom-config/,optional:file:./custom-config/,
则 Spring Boot 的查找路径为:
- optional:classpath:/;optional:classpath:/config/
- optional:file:./;optional:file:./config/;optional:file:./config/*/
- optional:classpath:/custom-config/
- optional:file:./custom-config/
通过spring.config.name可以改变 Spring Boot 将要寻找的属性文件的名称,
例如spring.config.name=myConfig,则 Spring Boot 会在上述路径中查找 myConfig.properties 和 myConfig.yaml 文件,而非 application.properties 和 application.yaml
spring.config.name/spring.config.location/spring.config.additional-location 变量必须在应用启动之前就设置(即可以在 environment / system / 命令行等中指定) envrionment
Spring Boot 中有 profile 的概念,并可通过spring.profiles.active属性值来控制激活某个或某些 profile。
之后,Spring Boot 会自动在上述路径加载 application-{active_profile}.properties 中对应的值覆盖。
通常spring.config.location只会指定一个文件或一个路径,不过也可指定多个,例如--spring.config.location=classpath:application.properties,classpath:config/application.properties。
注意:这里","与上文提到的 group 中";"的区别: 假设,spring.profiles.active=prod,live,而且有如下三个属性文件: /cfg application-live.properties /ext application-live.properties application-prod.properties 比较下 spring.config.location=classpath:/cfg/;classpath:/ext/ 与 spring.config.location= classpath:/cfg/,classpath:/ext/ 的区别? 前者,加载的属性文件及顺序为:
- /ext/application-prod.properties
- /cfg/application-live.properties
- /ext/application-live.properties
后者,加载的属性文件及顺序为:
- /cfg/application-live.properties
- /ext/application-prod.properties
- /ext/application-live.properties
在单元测试时,Spring Boot 会自动在 test classpath 下查找 application.properties 和 application.yaml 属性文件。
在测试类上,可以通过@TestPropertySource指定加载特定的属性文件、或指定多个属性值,或通过@TestPropertySources加载多个属性文件。
@TestPropertySource(value = "classpath:properties/foo.properties", properties = {
"external.test=abc"
})
// 指定多个属性文件
@TestPropertySources(
@TestPropertySource("classpath:properties/foo.properties"),
@TestPropertySource("classpath:properties/bar.properties")
)