搜尋
首頁Javajava教程SpringBoot容器刷新前怎麼回呼ApplicationContextInitializer

I. 專案準備

本文所建立的實例工程採用SpringBoot 2.2.1.RELEASE maven 3.5.3 idea進行開發

具體的SpringBoot專案工程創建就不贅述了,核心的pom文件,無需額外的依賴

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

II. 容器刷新前擴展點實例

1. 自訂ApplicationContextInitializer

當我們希望實作一個自訂的上下文初始化時,非常簡單,實作上面這個接口就行了,如

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

2. 擴充點註冊

上面自訂一個擴充點,如何使它生效呢?

官方提供了三種方式,如在啟動時,直接進行註冊: 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)) {
        }
    }
}

當我們的擴展點是放在一個jar包中對外提供時,使用上面的啟動註冊方式顯然是不可行的,此時更推薦的做法就是透過Spring的SPI機制進行註冊

在資源目錄下的META-INF/spring.factories檔案中進行註冊

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

#說明

  • 上面SPI的機制非常推薦大家使用,在先前的文章中,AutoConfiguration的註冊通常也是使用這種方式

除了上面的兩種註冊方式之外,另外還有一個設定檔的方式,在設定檔application.propertiesapplication.yml中,如下設定

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

啟動測試

#上面三種註冊方式,我們實作三個自訂的擴充點,然後啟動之後,看一下實際輸出

SpringBoot容器刷新前怎麼回呼ApplicationContextInitializer

#上面的輸出,可以簡單的得出一個結論,不同註冊方式的優先順序(為了更合理的驗證下面的觀點,推薦大家修改下上面三個自訂擴充點名,排除掉是因為副檔名導致的排序問題)

  • 設定檔註冊> SPI註冊> 啟動時註冊

3. 執行順序指定

#對於自訂的擴充點實現,當存在順序關係時,我們可以透過@Order註解來實現, 如當上面的三個擴展點都是透過啟動方式註冊時

@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)) {
        }
    }
}

輸出實例如下

SpringBoot容器刷新前怎麼回呼ApplicationContextInitializer

接著重點來了

  • 若上面的三個自訂實現,不是相同的註冊方式,如將03採用設定檔方式進行註冊,那麼01, 02 還是啟動註冊

  • 則順序是03 > 02 > 01

  • @Order 註解修飾的順序,並不能打破設定檔> SPI > 啟動方式註冊的順序

關於自訂實作類別的執行順序,規則如下

  • 設定檔> SPI > 啟動方式

  • #相同的註冊方式,可以透過@Order註解進行修飾,值越小則優先權越高

4. 使用場景範例

最後我們再來看一下,這個擴充點到底有什麼用,我們再什麼場景下會用到這個呢?

一個經常可以看到的應用場景如透過它來指定需要啟動的設定檔

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

但是一般也很少見到有人這麼做,因為直接使用設定參數就行了,那麼有場景需要這麼做麼?

答案當然是有的,例如現在廣為流行的docker容器部署,當我們希望每次都是打同一個鏡像,然後在實際運行的時候,根據不同的環境來決定當前鏡像到底啟用哪些配置文件,這時就有用了

例如我們通過容器的環境參數app.env 來獲取當前運行的環境,如果是prod,則激活application- prod.yml; 如果是test,則啟動application-test.yml

#那麼此時可以這麼幹

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("非法的环境参数:" + env);
        }
    }
}

以上是SpringBoot容器刷新前怎麼回呼ApplicationContextInitializer的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述
本文轉載於:亿速云。如有侵權,請聯絡admin@php.cn刪除
JVM中的類加載程序子系統如何促進平台獨立性?JVM中的類加載程序子系統如何促進平台獨立性?Apr 23, 2025 am 12:14 AM

類加載器通過統一的類文件格式、動態加載、雙親委派模型和平台無關的字節碼,確保Java程序在不同平台上的一致性和兼容性,實現平台獨立性。

Java編譯器會產生特定於平台的代碼嗎?解釋。Java編譯器會產生特定於平台的代碼嗎?解釋。Apr 23, 2025 am 12:09 AM

Java編譯器生成的代碼是平台無關的,但最終執行的代碼是平台特定的。 1.Java源代碼編譯成平台無關的字節碼。 2.JVM將字節碼轉換為特定平台的機器碼,確保跨平台運行但性能可能不同。

JVM如何處理不同操作系統的多線程?JVM如何處理不同操作系統的多線程?Apr 23, 2025 am 12:07 AM

多線程在現代編程中重要,因為它能提高程序的響應性和資源利用率,並處理複雜的並發任務。 JVM通過線程映射、調度機制和同步鎖機制,在不同操作系統上確保多線程的一致性和高效性。

在Java的背景下,'平台獨立性”意味著什麼?在Java的背景下,'平台獨立性”意味著什麼?Apr 23, 2025 am 12:05 AM

Java的平台獨立性是指編寫的代碼可以在任何安裝了JVM的平台上運行,無需修改。 1)Java源代碼編譯成字節碼,2)字節碼由JVM解釋執行,3)JVM提供內存管理和垃圾回收功能,確保程序在不同操作系統上運行。

Java應用程序仍然可以遇到平台特定的錯誤或問題嗎?Java應用程序仍然可以遇到平台特定的錯誤或問題嗎?Apr 23, 2025 am 12:03 AM

Javaapplicationscanindeedencounterplatform-specificissuesdespitetheJVM'sabstraction.Reasonsinclude:1)Nativecodeandlibraries,2)Operatingsystemdifferences,3)JVMimplementationvariations,and4)Hardwaredependencies.Tomitigatethese,developersshould:1)Conduc

雲計算如何影響Java平台獨立性的重要性?雲計算如何影響Java平台獨立性的重要性?Apr 22, 2025 pm 07:05 PM

云计算显著提升了Java的平台独立性。1)Java代码编译为字节码,由JVM在不同操作系统上执行,确保跨平台运行。2)使用Docker和Kubernetes部署Java应用,提高可移植性和可扩展性。

Java的平台獨立性在廣泛採用中扮演著什麼角色?Java的平台獨立性在廣泛採用中扮演著什麼角色?Apr 22, 2025 pm 06:53 PM

Java'splatformindependenceallowsdeveloperstowritecodeonceandrunitonanydeviceorOSwithaJVM.Thisisachievedthroughcompilingtobytecode,whichtheJVMinterpretsorcompilesatruntime.ThisfeaturehassignificantlyboostedJava'sadoptionduetocross-platformdeployment,s

容器化技術(例如Docker)如何影響Java平台獨立性的重要性?容器化技術(例如Docker)如何影響Java平台獨立性的重要性?Apr 22, 2025 pm 06:49 PM

容器化技術如Docker增強而非替代Java的平台獨立性。 1)確保跨環境的一致性,2)管理依賴性,包括特定JVM版本,3)簡化部署過程,使Java應用更具適應性和易管理性。

See all articles

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱工具

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

DVWA

DVWA

Damn Vulnerable Web App (DVWA) 是一個PHP/MySQL的Web應用程序,非常容易受到攻擊。它的主要目標是成為安全專業人員在合法環境中測試自己的技能和工具的輔助工具,幫助Web開發人員更好地理解保護網路應用程式的過程,並幫助教師/學生在課堂環境中教授/學習Web應用程式安全性。 DVWA的目標是透過簡單直接的介面練習一些最常見的Web漏洞,難度各不相同。請注意,該軟體中

mPDF

mPDF

mPDF是一個PHP庫,可以從UTF-8編碼的HTML產生PDF檔案。原作者Ian Back編寫mPDF以從他的網站上「即時」輸出PDF文件,並處理不同的語言。與原始腳本如HTML2FPDF相比,它的速度較慢,並且在使用Unicode字體時產生的檔案較大,但支援CSS樣式等,並進行了大量增強。支援幾乎所有語言,包括RTL(阿拉伯語和希伯來語)和CJK(中日韓)。支援嵌套的區塊級元素(如P、DIV),

SublimeText3 英文版

SublimeText3 英文版

推薦:為Win版本,支援程式碼提示!

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用