知識庫 / Spring / Spring Boot RSS 訂閱

Spring Boot 中的環境後處理器

Spring Boot
HongKong
6
01:25 PM · Dec 06 ,2025

1. 概述

自 Spring Boot 1.3 版本起,我們可以利用 EnvironmentPostProcessor在應用程序上下文刷新前自定義應用程序的 Environment

在本教程中,我們將學習如何將自定義屬性加載並轉換到 Environment 中,然後訪問這些屬性。

2. Spring Environment

Spring 中的 Environment 抽象代表當前應用程序運行的環境。同時,它致力於統一訪問各種屬性源中的方法,例如屬性文件、JVM 系統屬性、系統環境變量和 Servlet 上下文參數。

因此,在大多數情況下,自定義 Environment 意味着在將這些屬性暴露給 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

然後,我們可以很直接地將新的屬性添加到 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調用由此產生的system.getProperty類似於調用Java的System.getenv().get

只要這些屬性存在於環境中,我們將創建一個新的映射,prefixed 為了簡潔,我們跳過了rename的內容,但請查看代碼示例以獲取完整實現。 The resulting map has the same values as system,但具有前綴的鍵。

最後,我們將新的PropertySource添加到Environment。 現在,如果一個 Bean 詢問com.baeldung.environmentpostprocessor.calculation.modeEnvironment將會諮詢我們的映射。

順便説一下,EnvironmentPostProcessor的 Javadoc 鼓勵我們實現Ordered接口或使用@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 接口,以及兩個實現:GrossPriceCalculatorNetPriceCalculator

在我們的實現中,我們可以簡單地使用 @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

這段代碼之所以有效,是因為在 Spring Boot 自配置生效之前,自定義 EnvironmentPostProcessor 實現會被觸發。 這種結合使得 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 的實現能夠從不同位置加載各種格式的任意文件。 此外,我們還可以對屬性進行任何必要的轉換,以便將其方便地提供給 Environment 用於後續使用。 這種靈活性在將基於 Spring Boot 的應用程序與第三方配置集成時尤其有用。

user avatar
0 位用戶收藏了這個故事!
收藏

發佈 評論

Some HTML is okay.