溫馨提示×

溫馨提示×

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

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

SpringBoot容器刷新前怎么回調(diào)ApplicationContextInitializer

發(fā)布時(shí)間:2022-12-28 09:52:16 來源:億速云 閱讀:95 作者:iii 欄目:開發(fā)技術(shù)

本篇內(nèi)容介紹了“SpringBoot容器刷新前怎么回調(diào)ApplicationContextInitializer”的有關(guān)知識,在實(shí)際案例的操作過程中,不少人都會遇到這樣的困境,接下來就讓小編帶領(lǐng)大家學(xué)習(xí)一下如何處理這些情況吧!希望大家仔細(xì)閱讀,能夠?qū)W有所成!

I. 項(xiàng)目準(zhǔn)備

本文創(chuàng)建的實(shí)例工程采用SpringBoot 2.2.1.RELEASE + maven 3.5.3 + idea進(jìn)行開發(fā)

具體的SpringBoot項(xiàng)目工程創(chuàng)建就不贅述了,核心的pom文件,無需額外的依賴

配置文件 application.yml, 也沒有什么特殊的配置

II. 容器刷新前擴(kuò)展點(diǎn)實(shí)例

1. 自定義ApplicationContextInitializer

當(dāng)我們希望實(shí)現(xiàn)一個(gè)自定義的上下文初始化時(shí),非常簡單,實(shí)現(xiàn)上面這個(gè)接口就行了,如

public class ApplicationContextInitializer01 implements ApplicationContextInitializer {
    @Override
    public void initialize(ConfigurableApplicationContext configurableApplicationContext) {
        System.out.println("ApplicationContextInitializer01");
    }
}

2. 擴(kuò)展點(diǎn)注冊

上面自定義一個(gè)擴(kuò)展點(diǎn),如何使它生效呢?

官方提供了三種方式,如在啟動(dòng)時(shí),直接進(jìn)行注冊: springApplication.addInitializers(new ApplicationContextInitializer01());

@SpringBootApplication
public class Application {

    public static void main(String[] args) {
        SpringApplication springApplication = new SpringApplication(Application.class);
        springApplication.addInitializers(new ApplicationContextInitializer01());
        try (ConfigurableApplicationContext context = springApplication.run(args)) {
        }
    }
}

當(dāng)我們的擴(kuò)展點(diǎn)是放在一個(gè)jar包中對外提供時(shí),使用上面的啟動(dòng)注冊方式顯然是不可行的,此時(shí)更推薦的做法就是通過Spring的SPI機(jī)制進(jìn)行注冊

在資源目錄下的META-INF/spring.factories文件中進(jìn)行注冊

org.springframework.context.ApplicationContextInitializer=com.git.hui.extention.context.ApplicationContextInitializer02

說明

  • 上面SPI的機(jī)制非常推薦大家使用,在之前的文章中,AutoConfiguration的注冊通常也是使用這種方式

除了上面的兩種注冊方式之外,另外還有一個(gè)配置文件的方式,在配置文件application.propertiesapplication.yml中,如下配置

context:
  initializer:
    classes: com.git.hui.extention.context.ApplicationContextInitializer03

啟動(dòng)測試

上面三種注冊方式,我們實(shí)現(xiàn)三個(gè)自定義的擴(kuò)展點(diǎn),然后啟動(dòng)之后,看一下實(shí)際輸出

SpringBoot容器刷新前怎么回調(diào)ApplicationContextInitializer

上面的輸出,可以簡單的得出一個(gè)結(jié)論,不同注冊方式的優(yōu)先級(為了更合理的驗(yàn)證下面的觀點(diǎn),推薦大家修改下上面三個(gè)自定義擴(kuò)展點(diǎn)名,排除掉是因?yàn)閿U(kuò)展名導(dǎo)致的排序問題)

  • 配置文件注冊 > SPI注冊 > 啟動(dòng)時(shí)注冊

3. 執(zhí)行順序指定

對于自定義的擴(kuò)展點(diǎn)實(shí)現(xiàn),當(dāng)存在順序關(guān)系時(shí),我們可以通過@Order注解來實(shí)現(xiàn), 如當(dāng)上面的三個(gè)擴(kuò)展點(diǎn)都是通過啟動(dòng)方式注冊時(shí)

@Order(5)
public class ApplicationContextInitializer01 implements ApplicationContextInitializer {
    @Override
    public void initialize(ConfigurableApplicationContext configurableApplicationContext) {
        System.out.println("ApplicationContextInitializer01");
    }
}

@Order(2)
public class ApplicationContextInitializer02 implements ApplicationContextInitializer {
    @Override
    public void initialize(ConfigurableApplicationContext configurableApplicationContext) {
        System.out.println("ApplicationContextInitializer02");
    }
}

@Order(10)
public class ApplicationContextInitializer03 implements ApplicationContextInitializer {
    @Override
    public void initialize(ConfigurableApplicationContext configurableApplicationContext) {
        System.out.println("ApplicationContextInitializer03");
    }
}

@SpringBootApplication
public class Application {
    public static void main(String[] args) {
        SpringApplication springApplication = new SpringApplication(Application.class);
        springApplication.addInitializers(new ApplicationContextInitializer01(), new ApplicationContextInitializer02(), new ApplicationContextInitializer03());
        try (ConfigurableApplicationContext context = springApplication.run(args)) {
        }
    }
}

輸出實(shí)例如下

SpringBoot容器刷新前怎么回調(diào)ApplicationContextInitializer

接著重點(diǎn)來了

  • 若上面的三個(gè)自定義實(shí)現(xiàn),不是相同的注冊方式,如將03采用配置文件方式進(jìn)行注冊,那么01, 02 依然是啟動(dòng)注冊

  • 則順序是 03 > 02 > 01

  • @Order注解修飾的順序,并不能打破 配置文件 > SPI > 啟動(dòng)方式注冊的順序

關(guān)于自定義實(shí)現(xiàn)類的執(zhí)行順序,規(guī)則如下

  • 配置文件 > SPI > 啟動(dòng)方式

  • 相同的注冊方式,可以通過 @Order 注解進(jìn)行修飾,值越小則優(yōu)先級越高

4. 使用場景示例

最后我們再來看一下,這個(gè)擴(kuò)展點(diǎn)到底有什么用,我們再什么場景下會用到這個(gè)呢?

一個(gè)經(jīng)??梢钥吹降膽?yīng)用場景如通過它來指定需要激活的配置文件

public class ApplicationContextInitializer03 implements ApplicationContextInitializer {
    @Override
    public void initialize(ConfigurableApplicationContext configurableApplicationContext) {
        // 指定激活prod對應(yīng)的配置文件
        configurableApplicationContext.getEnvironment().setActiveProfiles("prod");
    }
}

但是一般也很少見到有人這么干,因?yàn)橹苯邮褂门渲脜?shù)就行了,那么有場景需要這么做么?

答案當(dāng)然是有的,比如現(xiàn)在廣為流行的docker容器部署,當(dāng)我們希望每次都是打同一個(gè)鏡像,然后在實(shí)際運(yùn)行的時(shí)候,根據(jù)不同的環(huán)境來決定當(dāng)前鏡像到底啟用哪些配置文件,這時(shí)就有用了

比如我們通過容器的環(huán)境參數(shù) app.env 來獲取當(dāng)前運(yùn)行的環(huán)境,如果是prod,則激活application-prod.yml; 如果是test,則激活application-test.yml

那么此時(shí)可以這么干

public class EenvActiveApplicationContextInitializer implements ApplicationContextInitializer {
    @Override
    public void initialize(ConfigurableApplicationContext configurableApplicationContext) {
        String env = System.getenv("app.env");
        if ("prod".equalsIgnoreCase(env)) {
            configurableApplicationContext.getEnvironment().setActiveProfiles("prod");
        } else if ("test".equalsIgnoreCase(env)) {
            configurableApplicationContext.getEnvironment().setActiveProfiles("test");
        } else {
            throw new RuntimeException("非法的環(huán)境參數(shù):" + env);
        }
    }
}

“SpringBoot容器刷新前怎么回調(diào)ApplicationContextInitializer”的內(nèi)容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業(yè)相關(guān)的知識可以關(guān)注億速云網(wǎng)站,小編將為大家輸出更多高質(zhì)量的實(shí)用文章!

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

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

AI