首頁 > Java > java教程 > SpringBoot的EnvironmentPostProcessor怎麼用

SpringBoot的EnvironmentPostProcessor怎麼用

PHPz
發布: 2023-05-22 09:25:05
轉載
1573 人瀏覽過

    一、背景

    之前專案中用到了Apollo配置中心,對接Apollo配置中心後,配置中心的屬性就可以在程式中使用了,那麼這個是怎麼實現的呢?配置中心的屬性又是何時載入到程式中的呢?那我們如果找到了這個是怎麼實現的是否就可以 從任何地方載入配置屬性配置屬性的加解密功能呢

    二、需求

    SpringBoot的EnvironmentPostProcessor怎麼用

    從上圖得知,我們的需求很簡單,也就是我們自己定義的屬性需要比設定檔中的優先順序更高。

    三、分析

    1、什麼時候加入SpringBoot加入我們自己的設定屬性

    當我們想要在Bean中使用設定屬性時,那麼我們的配置屬性必須在Bean實例化之前就放入到Spring到Environment。即我們的介面需要在 application context refreshed 之前進行調用,而 EnvironmentPostProcessor 正好可以實作這個功能。

    2、取得配置屬性的優先權

    我們知道在 Spring中取得屬性是有優先權的。
    例如我們存在如下配置屬性 username

    ├─application.properties
    │   >> username=huan
    ├─application-dev.properties
    │   >> username=huan.fu
    登入後複製

    那麼此時 username 的值是什麼呢?這裡借用 Apollo的一張圖來說解釋一下這個問題。

    參考連結:https://www.apolloconfig.com/#/zh/design/apollo-design

    SpringBoot的EnvironmentPostProcessor怎麼用

    Spring從3.1版本開始增加了ConfigurableEnvironmentPropertySource

    ConfigurableEnvironment
    登入後複製
    • Spring的ApplicationContext會包含一個Environment(實作ConfigurableEnvironment介面)

    ConfigurableEnvironment本身包含了許多PropertySource

    PropertySource

    SpringBoot的EnvironmentPostProcessor怎麼用

    屬性來源

    SpringBoot的EnvironmentPostProcessor怎麼用

    SpringBoot的EnvironmentPostProcessor怎麼用


    ##可以理解為很多Key - Value的屬性配置

    由上方的原理圖可知,

    key在最開始出現的 PropertySource中的優先權較高,上面的範例在SpringBoot

    usernameSpringBoot的EnvironmentPostProcessor怎麼用的值為

    huan.fu

    3、何時加入我們自己的配置

    由第二步驟

    取得配置屬性的優先權

    可知,SpringBoot的EnvironmentPostProcessor怎麼用PropertySource

    越靠前越先執行,那麼要我們配置生效,就必須放在越前面越好。

    由上圖可知,SpringBoot載入各種設定是透過EnvironmentPostProcessor來實現的,而具體的實作是

    ConfigDataEnvironmentPostProcessor

    來實現的。然後我們自己寫一個

    EnvironmentPostProcessor
      的實作類,然後在
    • ConfigDataEnvironmentPostProcessor

      後執行,並加入到

      Environment###中的第一位即可。 ###############四、實作######1、引入SpringBoot依賴###
      <?xml version="1.0" encoding="UTF-8"?>
      <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
               xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
          <modelVersion>4.0.0</modelVersion>
          <parent>
              <groupId>org.springframework.boot</groupId>
              <artifactId>spring-boot-starter-parent</artifactId>
              <version>2.6.6</version>
              <relativePath/> <!-- lookup parent from repository -->
          </parent>
          <groupId>com.huan.springcloud</groupId>
          <artifactId>springboot-extension-point</artifactId>
          <version>0.0.1-SNAPSHOT</version>
          <name>springboot-extension-point</name>
          <properties>
              <java.version>1.8</java.version>
          </properties>
          <dependencies>
              <dependency>
                  <groupId>org.springframework.boot</groupId>
                  <artifactId>spring-boot-starter-web</artifactId>
              </dependency>
          </dependencies>
      </project>
      登入後複製
      ###2、在application.properties中配置屬性####
      vim application.properties
      登入後複製
      username=huan
      登入後複製
      # ##3、寫自訂屬性並加入Spring Environment中################注意:###1、如果發現程式中日誌沒有輸出,檢查是否使用了### slf4j###輸出日誌,此時因為日誌系統未初始化無法輸出日誌。 ###解決方法如下:######
      SpringBoot版本
      		>= 2.4 可以参考上图中的使用 DeferredLogFactory 来输出日志
      		< 2.4
      			1、参考如下链接 https://stackoverflow.com/questions/42839798/how-to-log-errors-in-a-environmentpostprocessor-execution
      			2、核心代码:
      				@Component
      				public class MyEnvironmentPostProcessor implements
      				        EnvironmentPostProcessor, ApplicationListener<ApplicationEvent> {
      				    private static final DeferredLog log = new DeferredLog();
      				    @Override
      				    public void postProcessEnvironment(
      				            ConfigurableEnvironment env, SpringApplication app) {
      				        log.error("This should be printed");
      				    }
      				    @Override
      				    public void onApplicationEvent(ApplicationEvent event) {
      				        log.replayTo(MyEnvironmentPostProcessor.class);
      				    }
      				}
      登入後複製
      ###4、透過SPI使自訂的設定生效######1、在###src/main/resources###下新建# ##META-INF/spring.factories###檔案###############2、設定###
      org.springframework.boot.env.EnvironmentPostProcessor=\
        com.huan.springcloud.extensionpoint.environmentpostprocessor.CustomEnvironmentPostProcessor
      登入後複製
      ###5、編寫測試類,輸出定義的username 屬性的值###
      @Component
      public class PrintCustomizeEnvironmentProperty implements ApplicationRunner {
      
          private static final Logger log = LoggerFactory.getLogger(PrintCustomizeEnvironmentProperty.class);
          @Value("${username}")
          private String userName;
          @Override
          public void run(ApplicationArguments args) {
              log.info("获取到的 username 的属性值为: {}", userName);
          }
      }
      登入後複製
      ###6、運行結果###############五、注意事項######1、日誌無法輸出#######參考上方的###3、編寫自訂屬性並加入Spring Environment中###提供的解決方案。 ######2、設定沒有生效檢查############檢查EnvironmentPostProcessor的優先權,看看是否@Order或Ordered傳回的優先權值不對。 ###
    • 看看别的地方是否实现了 EnvironmentPostProcessor或ApplicationContextInitializer或BeanFactoryPostProcessor或BeanDefinitionRegistryPostProcessor等这些接口,在这个里面修改了 PropertySource的顺序。

    • 理解 Spring 获取获取属性的顺序 参考 2、获取配置属性的优先级

    3、日志系统如何初始化

    如下代码初始化日志系统

    org.springframework.boot.context.logging.LoggingApplicationListener
    登入後複製

    以上是SpringBoot的EnvironmentPostProcessor怎麼用的詳細內容。更多資訊請關注PHP中文網其他相關文章!

    來源:yisu.com
    本網站聲明
    本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
    熱門教學
    更多>
    最新下載
    更多>
    網站特效
    網站源碼
    網站素材
    前端模板