溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

SpringBoot的EnvironmentPostProcessor怎么用

發(fā)布時(shí)間:2022-04-25 16:10:48 來(lái)源:億速云 閱讀:677 作者:iii 欄目:開發(fā)技術(shù)

今天小編給大家分享一下SpringBoot的EnvironmentPostProcessor怎么用的相關(guān)知識(shí)點(diǎn),內(nèi)容詳細(xì),邏輯清晰,相信大部分人都還太了解這方面的知識(shí),所以分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后有所收獲,下面我們一起來(lái)了解一下吧。

    一、背景

    之前項(xiàng)目中用到了Apollo配置中心,對(duì)接Apollo配置中心后,配置中心的屬性就可以在程序中使用了,那么這個(gè)是怎么實(shí)現(xiàn)的呢?配置中心的屬性又是何時(shí)加載到程序中的呢?那么我們?nèi)绻业搅诉@個(gè)是怎么實(shí)現(xiàn)的是否就可以 從任何地方加載配置屬性、配置屬性的加解密功能呢

    二、需求

    SpringBoot的EnvironmentPostProcessor怎么用

    從上圖中得知,我們的需求很簡(jiǎn)單,即我們自己定義的屬性需要比配置文件中的優(yōu)先級(jí)更高。

    三、分析

    1、什么時(shí)候向SpringBoot中加入我們自己的配置屬性

    當(dāng)我們想在Bean中使用配置屬性時(shí),那么我們的配置屬性必須在Bean實(shí)例化之前就放入到Spring到Environment中。即我們的接口需要在 application context refreshed 之前進(jìn)行調(diào)用,而 EnvironmentPostProcessor 正好可以實(shí)現(xiàn)這個(gè)功能。

    2、獲取配置屬性的優(yōu)先級(jí)

    我們知道在 Spring中獲取屬性是有優(yōu)先級(jí)的。
    比如我們存在如下配置屬性 username

    ├─application.properties
    │   >> username=huan
    ├─application-dev.properties
    │   >> username=huan.fu

    那么此時(shí) username 的值是什么呢?此處借用 Apollo的一張圖來(lái)說(shuō)解釋一下這個(gè)問題。

    參考鏈接:https://www.apolloconfig.com/#/zh/design/apollo-design

    SpringBoot的EnvironmentPostProcessor怎么用

    Spring從3.1版本開始增加了ConfigurableEnvironmentPropertySource

    ConfigurableEnvironment
    • Spring的ApplicationContext會(huì)包含一個(gè)Environment(實(shí)現(xiàn)ConfigurableEnvironment接口)

    • ConfigurableEnvironment自身包含了很多個(gè)PropertySource

    PropertySource

    • 屬性源

    • 可以理解為很多個(gè)Key - Value的屬性配置

    由上方的原理圖可知,key在最開始出現(xiàn)的PropertySource中的優(yōu)先級(jí)更高,上面的例子在SpringBootusername的值為huan.fu

    3、何時(shí)加入我們自己的配置

    由第二步 獲取配置屬性的優(yōu)先級(jí) 可知,PropertySource 越靠前越先執(zhí)行,那么要我們配置生效,就必須放在越前面越好。

    SpringBoot的EnvironmentPostProcessor怎么用

    由上圖可知,SpringBoot加載各種配置是通過EnvironmentPostProcessor來(lái)實(shí)現(xiàn)的,而具體的實(shí)現(xiàn)是ConfigDataEnvironmentPostProcessor來(lái)實(shí)現(xiàn)的。那么我們自己編寫一個(gè)EnvironmentPostProcessor的實(shí)現(xiàn)類,然后在ConfigDataEnvironmentPostProcessor后執(zhí)行,并加入到 Environment中的第一位即可。

    SpringBoot的EnvironmentPostProcessor怎么用

    四、實(shí)現(xiàn)

    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中

    SpringBoot的EnvironmentPostProcessor怎么用

    注意:
    1、如果發(fā)現(xiàn)程序中日志沒有輸出,檢查是否使用了slf4j輸出日志,此時(shí)因?yàn)槿罩鞠到y(tǒng)未初始化無(wú)法輸出日志。解決方法如下:

    SpringBoot版本
    		>= 2.4 可以參考上圖中的使用 DeferredLogFactory 來(lái)輸出日志
    		< 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文件

    SpringBoot的EnvironmentPostProcessor怎么用

    2、配置

    org.springframework.boot.env.EnvironmentPostProcessor=\
      com.huan.springcloud.extensionpoint.environmentpostprocessor.CustomEnvironmentPostProcessor

    5、編寫測(cè)試類,輸出定義的 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、運(yùn)行結(jié)果

    SpringBoot的EnvironmentPostProcessor怎么用

    五、注意事項(xiàng)

    1、日志無(wú)法輸出

    參考上方的 3、編寫自定義屬性并加入Spring Environment中提供的解決方案。

    2、配置沒有生效檢查

    • 檢查EnvironmentPostProcessor的優(yōu)先級(jí),看看是否@Order或者Ordered返回的優(yōu)先級(jí)值不對(duì)。

    • 看看別的地方是否實(shí)現(xiàn)了 EnvironmentPostProcessor或ApplicationContextInitializer或BeanFactoryPostProcessor或BeanDefinitionRegistryPostProcessor等這些接口,在這個(gè)里面修改了 PropertySource的順序。

    • 理解 Spring 獲取獲取屬性的順序 參考 2、獲取配置屬性的優(yōu)先級(jí)

    3、日志系統(tǒng)如何初始化

    如下代碼初始化日志系統(tǒng)

    org.springframework.boot.context.logging.LoggingApplicationListener

    以上就是“SpringBoot的EnvironmentPostProcessor怎么用”這篇文章的所有內(nèi)容,感謝各位的閱讀!相信大家閱讀完這篇文章都有很大的收獲,小編每天都會(huì)為大家更新不同的知識(shí),如果還想學(xué)習(xí)更多的知識(shí),請(qǐng)關(guān)注億速云行業(yè)資訊頻道。

    向AI問一下細(xì)節(jié)

    免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

    AI