Spring 的 Environment 结合了两个关注点:解析配置属性,以及确定哪些 Bean 定义配置文件处于激活状态。核心框架定义了抽象以及标准 JVM/Servlet 来源;Spring Boot 则增加了自己的外部配置来源和优先级规则。
属性源与优先级 #
可配置环境在 MutablePropertySources 中维护按顺序排列的 PropertySource<?> 对象。解析会从优先级最高的源开始,依次向优先级较低的源搜索,并返回包含所请求键的第一个源中的值。显式命名和排序属性源,可以避免配置随注册顺序变化:
ConfigurableEnvironment environment = context.getEnvironment();
environment.getPropertySources().addFirst(
new MapPropertySource("deployment", Map.of("orders.timeout", "2s")));StandardEnvironment 包含 JVM 系统属性和操作系统环境变量。StandardServletEnvironment 增加 Servlet 配置、Servlet 上下文参数,并可选地增加 JNDI 源。在处理配置类时,@PropertySource 可以添加属性资源。
源的顺序是一项策略,而不是一条要求每个文件、JVM 属性或环境变量都必须获胜的内在规则。Spring Boot 定义了一个更大的、已文档化的顺序,其中包括配置数据和命令行参数。测试应添加显式的测试源,而不应依赖开发者机器的环境。
解析、默认值与类型 #
PropertyResolver API 支持直接查找和类型化查找:
Duration timeout =
environment.getProperty("orders.timeout", Duration.class, Duration.ofSeconds(1));类型化访问会委托给已配置的转换服务。占位符语法支持 ${orders.timeout},以及 ${orders.timeout:1s} 这样的回退值。上下文具有适当的嵌入值解析器时,@Value 会使用占位符解析;在显式的非 Boot 配置中,PropertySourcesPlaceholderConfigurer 提供该功能。
只有当默认值在运行层面有效时,回退值才适用。可以在 Bean 使用必需配置之前声明并校验它:
environment.setRequiredProperties("database.url", "database.user");
environment.validateRequiredProperties();未解析的必需占位符应使启动失败,而不是静默选择不适合生产环境的值。密钥应通过受控的属性源输入,并且在诊断解析问题时不得打印。
配置文件表达式 #
@Profile 使组件或配置类根据激活的配置文件进行条件化。配置文件表达式支持名称、使用 ! 的否定、使用 & 的合取、使用 | 的析取以及括号:
@Configuration
@Profile("production & !maintenance")
class ProductionConfiguration {
}对于 @Profile({"blue", "green"}) 这样的数组,只要任一元素匹配,组件就会被激活。未指定配置文件的定义无论激活集合为何都保持可用。
未显式激活任何配置文件时,Spring 使用默认配置文件集合,其初始值包含 default。spring.profiles.default 可以更改该集合。因此,标记为 @Profile("default") 的 Bean 是有条件的;当另一个配置文件处于激活状态时,它不会成为无条件的回退实现。
激活配置文件 #
可以在刷新之前以编程方式选择配置文件:
var context = new AnnotationConfigApplicationContext();
context.getEnvironment().setActiveProfiles("integration");
context.register(TestConfiguration.class);
context.refresh();配置文件也可以来自 spring.profiles.active 属性。JVM 参数 -Dspring.profiles.active=production 可与核心标准环境配合使用。根据 Boot 的外部配置规则,Spring Boot 还接受命令行配置以及诸如 SPRING_PROFILES_ACTIVE 这样的宽松环境变量名称。根据使用 setActiveProfiles 还是 addActiveProfile,编程调用会替换环境的激活集合,或向其中添加配置文件。
确定性配置 #
在生产环境和测试中应用相同的显式策略:
- 记录源名称和优先级。
- 在刷新上下文之前激活配置文件。
- 对测试拥有的值使用
@TestPropertySource或@DynamicPropertySource。 - 在专门的配置测试中断言关键的已解析值。
- 保持配置文件的粒度较粗;对于值使用属性,而不是为每种配置组合创建一个配置文件。
评论
在 GitHub 上阅读或评论(发表评论需要登录)