查看原文
其他

Spring Boot的EnvironmentPostProcessor

康仔 SpringForAll社区 2021-05-27

我刚刚宣布了新的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接口.

我们将用它来读取几个环境变量:

  1. calculation_mode=GROSS

  2. gross_calculation_tax_rate=0.15

我们将使用后处理器以特定于应用程序的方式公开这些,在本例中使用自定义前缀:

  1. com.baeldung.environmentpostprocessor.calculation.mode=GROSS

  2. com.baeldung.environmentpostprocessor.gross.calculation.tax.rate=0.15

然后,我们可以很简单地将我们的新属性添加到环境中:

  1. @Order(Ordered.LOWEST_PRECEDENCE)

  2. public class PriceCalculationEnvironmentPostProcessor implements EnvironmentPostProcessor {


  3. @Override

  4. public void postProcessEnvironment(ConfigurableEnvironment environment,

  5. SpringApplication application) {

  6. PropertySource<?> system = environment.getPropertySources()

  7. .get(SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME);

  8. if (!hasOurPriceProperties(system)) {

  9. // error handling code omitted

  10. }

  11. Map<String, Object> prefixed = names.stream()

  12. .collect(Collectors.toMap(this::rename, system::getProperty));

  13. environment.getPropertySources()

  14. .addAfter(SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME, new MapPropertySource("prefixer", prefixed));

  15. }


  16. }

看看我们做了什么。首先,我们要求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中注册该类:

  1. org.springframework.boot.env.EnvironmentPostProcessor=

  2. com.baeldung.environmentpostprocessor.PriceCalculationEnvironmentPostProcessor

3.3. 使用@Value注解访问属性

让我们在几个类中使用这些。在示例中,我们有一个 PriceCalculator接口,它有两种实现:GrossPriceCalculator和NetPriceCalculator。

在我们的实现中, 我们可以使用@Value来检索我们的新属性:

  1. public class GrossPriceCalculator implements PriceCalculator {

  2. @Value("${com.baeldung.environmentpostprocessor.gross.calculation.tax.rate}")

  3. double taxRate;


  4. @Override

  5. public double calculate(double singlePrice, int quantity) {

  6. //calcuation implementation omitted

  7. }

  8. }

这很好,因为它与我们访问任何其他属性的方式相同,就像我们在application.properties中定义的那些属性一样。

3.4. 访问Spring Boot自动配置中的属性

现在,让我们来看一个复杂的例子,其中我们在Spring Boot 自动配置中访问前面的属性。

我们将创建自动配置类来读取这些属性。该类将根据不同的属性值初始化和连接应用程序上下文中的bean:

  1. @Configuration

  2. @AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE)

  3. public class PriceCalculationAutoConfig {

  4. @Bean

  5. @ConditionalOnProperty(name =

  6. "com.baeldung.environmentpostprocessor.calculation.mode", havingValue = "NET")

  7. @ConditionalOnMissingBean

  8. public PriceCalculator getNetPriceCalculator() {

  9. return new NetPriceCalculator();

  10. }


  11. @Bean

  12. @ConditionalOnProperty(name =

  13. "com.baeldung.environmentpostprocessor.calculation.mode", havingValue = "GROSS")

  14. @ConditionalOnMissingBean

  15. public PriceCalculator getGrossPriceCalculator() {

  16. return new GrossPriceCalculator();

  17. }

  18. }

与EnvironmentPostProcessor实现类似,自动配置类需要在ETA-INF/spring.factories中注册:

  1. org.springframework.boot.autoconfigure.EnableAutoConfiguration=

  2. com.baeldung.environmentpostprocessor.autoconfig.PriceCalculationAutoConfig

这是因为自定义EnvironmentPostProcessor 实现在Spring Boot自动配置之前就开始工作了。这种组合使Spring Boot自动配置更加强大。

关于Spring Boot自动配置的更多细节,请参阅关于使用Spring Boot进行自定义自动配置的文章。

4. 测试自定义实现

现在可以测试我们的代码了。Windows系统中我通过运行下面命令设置环境变量:

  1. set calculation_mode=GROSS

  2. set gross_calculation_tax_rate=0.15

Linux/Unix系统中,我们能运行下面命令设置环境变量:

  1. export calculation_mode=GROSS

  2. export gross_calculation_tax_rate=0.15

之后,我们可以运行mvn spring-boot:run命令开始测试:

  1. mvn spring-boot:run

  2. -Dstart-class=com.baeldung.environmentpostprocessor.PriceCalculationApplication

  3. -Dspring-boot.run.arguments="100,4"

5. 结论

总而言之,EnvironmentPostProcessor实现能够从不同的位置加载各种格式的任意文件。此外,我们可以执行任何需要的转换,以使属性在环境中随时可用,以供以后使用。当我们将基于Spring boot的应用程序与第三方配置集成在一起时,这种自由无疑是有用的。

源码能在以下 Github库找到.

原文链接:https://www.baeldung.com/spring-boot-environmentpostprocessor

作者:baeldung

译者:康仔


推荐:Spring Cloud Alibaba基础教程:使用Nacos实现服务注册与发现

上一篇:JDK10 之前仍有缺陷的Java Stream API




 关注公众号

点击原文阅读更多



    您可能也对以下帖子感兴趣

    文章有问题?点此查看未经处理的缓存