Spring BootのEnvironmentPostProcessor

1. 概要

Spring Boot 1.3では、アプリケーションコンテキストが更新される前に、before_EnvironmentPostProcessor_を使用して*アプリケーションの_Environment_をカスタマイズできます*。
このチュートリアルでは、カスタムプロパティを_Environment、_に読み込んで変換し、それらのプロパティにアクセスする方法を見てみましょう__.__

2. 春の_環境_

Springの_Environment_抽象化は、現在のアプリケーションが実行されている環境を表します。 一方で、プロパティファイル、JVMシステムプロパティ、システム環境変数、サーブレットコンテキストパラメータなど、さまざまなプロパティソースのプロパティにアクセスする方法を統一する傾向があります。
*そのため、ほとんどの場合、_Environment_のカスタマイズは、さまざまなプロパティがBeanに公開される前に操作することを意味します。*開始するには、以前の記事link:/properties-with-spring [操作時に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
その後、新しいプロパティを_Environment_に簡単に追加できます。
@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));
    }

}
ここで行ったことを見てみましょう。 まず、環境変数の_PropertySource_を提供するように_environment_に依頼しました。*結果の_system.getProperty_を呼び出すことは、Javaの_System.getenv()。get._を呼び出すことに似ています。
次に、これらのプロパティが環境に存在する限り、*新しいマップを作成します* _ *プレフィックス付き。 。 *結果のマップは_system_と同じ値を持ちますが、キーが前に付きます*
最後に、新しい__PropertySource __を_Environment._に追加します。Beanが_com.baeldung.environmentpostprocessor.calculation.mode_を要求した場合、_Environment_はマップを参照します。
ところで、https://github.com/spring-projects/spring-boot/blob/v2.1.3.RELEASE/spring-boot-project/spring-boot/src/main/java/org/springframework /boot/env/EnvironmentPostProcessor.java#L31[_EnvironmentPostProcessor_'s Javadoc]は、_Ordered_インターフェースを実装するか、https://www.baeldung.com/spring-order [_ @ 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_注釈を使用してプロパティにアクセスする

これらをいくつかのクラスで使用しましょう。 サンプルでは、​​_GrossPriceCalculator_と_NetPriceCalculator._の2つの実装を持つ__PriceCalculator ___interfaceがあります。
実装では、* https://www.baeldung.com/spring-value-annotation [単に_ @ 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_実装と同様に、自動構成クラスも_META-INF / spring.factories_に登録する必要があります。
org.springframework.boot.autoconfigure.EnableAutoConfiguration=
  com.baeldung.environmentpostprocessor.autoconfig.PriceCalculationAutoConfig
これは、*カスタム_EnvironmentPostProcessor_実装が、Spring Bootの自動構成が実行される前に開始されるためです*。 この組み合わせにより、Spring Bootの自動構成がより強力になります。
また、Spring Bootの自動構成の詳細については、https://www.baeldung.com/spring-boot-custom-auto-configuration [Spring Bootによるカスタム自動構成]の記事をご覧ください。

4. カスタム実装をテストする

次に、コードをテストします。 以下を実行して、Windowsのシステム環境変数を設定できます。
set calculation_mode=GROSS
set gross_calculation_tax_rate=0.15
または、Linux / Unixでは、代わりにそれらを_export_できます:
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_実装はさまざまな場所からさまざまな形式の任意のファイルをロードできます。*さらに、後で使用するために_Environment_でプロパティをすぐに利用できるようにするために必要な変換を行うことができます。 Spring Bootベースのアプリケーションをサードパーティの構成と統合する場合、この自由は確かに役立ちます。
ソースコードはhttps://github.com/eugenp/tutorials/tree/master/spring-boot-ops[Githubリポジトリ]にあります。