Spring Boot的EnvironmentPostProcessor
我刚刚宣布了新的Learn Spring课程,重点是Spring 5和Spring Boot 2的基础知识:
1.概述
从Spring Boot 1.3开始,我们可以使用Environment postprocessor在刷新应用程序上下文之前, 定制应用程序的环境。
在本教程中,让我们看看如何加载自定义属性并将其转换到环境中,然后访问这些属性。
2. Spring Environment
Spring中的环境 抽象表示当前应用程序运行的环境。同时,它倾向于统一访问各种属性源(如属性文件、JVM系统属性、系统环境变量和servlet上下文参数)中的属性的方法。
因此,在大多数情况下,自定义环境意味着在各种属性暴露到bean之前对它们进行操作。首先,请访问我们之前关于使用Spring操作属性的文章。
3. 一个简单的例子
现在让我们构建一个简单的价格计算应用程序。它将以基于总收入或基于净额的模式计算价格。来自第三方的系统环境变量将决定选择哪种计算模式。
3.1. 实现 EnvironmentPostProcessor
为此,让我们实现EnvironmentPostProcessor接口.
我们将用它来读取几个环境变量:
calculation_mode=GROSS
gross_calculation_tax_rate=0.15
我们将使用后处理器以特定于应用程序的方式公开这些,在本例中使用自定义前缀:
com.baeldung.environmentpostprocessor.calculation.mode=GROSS
com.baeldung.environmentpostprocessor.gross.calculation.tax.rate=0.15
然后,我们可以很简单地将我们的新属性添加到环境中:
@Order(Ordered.LOWEST_PRECEDENCE)
public class PriceCalculationEnvironmentPostProcessor implements EnvironmentPostProcessor {
@Override
public void postProcessEnvironment(ConfigurableEnvironment environment,
SpringApplication application) {
PropertySource<?> system = environment.getPropertySources()
.get(SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME);
if (!hasOurPriceProperties(system)) {
// error handling code omitted
}
Map<String, Object> prefixed = names.stream()
.collect(Collectors.toMap(this::rename, system::getProperty));
environment.getPropertySources()
.addAfter(SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME, new MapPropertySource("prefixer", prefixed));
}
}
看看我们做了什么。首先,我们要求environment为环境变量提供PropertySource。调用生成的system.getProperty 类似于调用Java的System.getenv().get 。
然后,只要这些属性存在于环境中,我们将创建一个新的前缀的map。 为简洁起见,我们将跳过rename 的内容,但请查看完整实现的代码示例。创建的map具有与system相同的值,但是带有前缀键。
最后,我们将向环境添加新的PropertySource 。现在,如果bean请求com.baeldung.environmentpostprocessor.calculation.mode ,环境 将检查我们的map。.
顺便注意,EnvironmentPostProcessor的 Javadoc鼓励我们要么实现有序接口,要么使用@Order 注解。
当然,这只是一个属性源。Spring Boot允许我们满足多种资源和格式。
3.2. spring的.factories中注册
为了在Spring Boot启动过程中调用实现,我们需要在META-INF/spring.factories中注册该类:
org.springframework.boot.env.EnvironmentPostProcessor=
com.baeldung.environmentpostprocessor.PriceCalculationEnvironmentPostProcessor
3.3. 使用@Value注解访问属性
让我们在几个类中使用这些。在示例中,我们有一个 PriceCalculator接口,它有两种实现:GrossPriceCalculator和NetPriceCalculator。
在我们的实现中, 我们可以使用@Value来检索我们的新属性:
public class GrossPriceCalculator implements PriceCalculator {
@Value("${com.baeldung.environmentpostprocessor.gross.calculation.tax.rate}")
double taxRate;
@Override
public double calculate(double singlePrice, int quantity) {
//calcuation implementation omitted
}
}
这很好,因为它与我们访问任何其他属性的方式相同,就像我们在application.properties中定义的那些属性一样。
3.4. 访问Spring Boot自动配置中的属性
现在,让我们来看一个复杂的例子,其中我们在Spring Boot 自动配置中访问前面的属性。
我们将创建自动配置类来读取这些属性。该类将根据不同的属性值初始化和连接应用程序上下文中的bean:
@Configuration
@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE)
public class PriceCalculationAutoConfig {
@Bean
@ConditionalOnProperty(name =
"com.baeldung.environmentpostprocessor.calculation.mode", havingValue = "NET")
@ConditionalOnMissingBean
public PriceCalculator getNetPriceCalculator() {
return new NetPriceCalculator();
}
@Bean
@ConditionalOnProperty(name =
"com.baeldung.environmentpostprocessor.calculation.mode", havingValue = "GROSS")
@ConditionalOnMissingBean
public PriceCalculator getGrossPriceCalculator() {
return new GrossPriceCalculator();
}
}
与EnvironmentPostProcessor实现类似,自动配置类需要在ETA-INF/spring.factories中注册:
org.springframework.boot.autoconfigure.EnableAutoConfiguration=
com.baeldung.environmentpostprocessor.autoconfig.PriceCalculationAutoConfig
这是因为自定义EnvironmentPostProcessor 实现在Spring Boot自动配置之前就开始工作了。这种组合使Spring Boot自动配置更加强大。
关于Spring Boot自动配置的更多细节,请参阅关于使用Spring Boot进行自定义自动配置的文章。
4. 测试自定义实现
现在可以测试我们的代码了。Windows系统中我通过运行下面命令设置环境变量:
set calculation_mode=GROSS
set gross_calculation_tax_rate=0.15
Linux/Unix系统中,我们能运行下面命令设置环境变量:
export calculation_mode=GROSS
export gross_calculation_tax_rate=0.15
之后,我们可以运行mvn spring-boot:run命令开始测试:
mvn spring-boot:run
-Dstart-class=com.baeldung.environmentpostprocessor.PriceCalculationApplication
-Dspring-boot.run.arguments="100,4"
5. 结论
总而言之,EnvironmentPostProcessor实现能够从不同的位置加载各种格式的任意文件。此外,我们可以执行任何需要的转换,以使属性在环境中随时可用,以供以后使用。当我们将基于Spring boot的应用程序与第三方配置集成在一起时,这种自由无疑是有用的。
源码能在以下 Github库找到.
原文链接:https://www.baeldung.com/spring-boot-environmentpostprocessor
作者:baeldung
译者:康仔
关注公众号
点击原文阅读更多