Spring Framework 6.0.0-M3 中的初始 AOT 支援

工程 | Stéphane Nicoll | 2022年3月22日 | ...

熟悉 Spring Native 實驗性專案的朋友們都知道,自 2019 年以來,Spring 團隊一直在為 Spring 應用程式開發原生映象支援。在 2021 年 3 月 首次釋出 Beta 版 之後,我們在 2021 年 12 月對 Spring Native 的工作進行了 大規模的修訂

我們還在去年的 SpringOne 大會上宣佈,我們計劃在 2022 年將這項工作推廣到 Spring Framework 6.0 正式版。在釋出第三個里程碑版本之後,這篇博文將帶您瞭解已包含的內容以及接下來的計劃。

提前編譯 (Ahead-Of-Time) 處理

提前處理應用程式上下文為最佳化打開了許多大門。根據具體情況,我們可以減少我們分發的程式碼量,預先計算您在元件中宣告的某些功能,從而加快啟動速度,並識別在受限環境中可能出現問題的項,為它們提供替代方案。

Spring Framework 6.0.0-M3 提供了基於 Spring Native 的首批功能,並進行了擴充套件審查和整合到核心容器中。它不是作為新功能以附加模組的形式出現,而是深度整合到現有核心功能中。目前包括:

  • 一個引擎,它處理給定類路徑上的 ApplicationContext,並貢獻程式碼提供其最佳化版本。
  • 一個用於貢獻執行時提示的新 API:整合商通常在他們需要在自己的元件中使用反射,或者需要訪問類路徑上的某些資源時使用它。這些提示與 GraalVM 相容,我們提供了生成適當配置檔案所需的基礎設施。

在構建時最佳化應用程式

當典型的 Spring 應用程式執行時,應用程式上下文會呼叫許多後置處理器來準備 bean 工廠:解析配置類、掃描類路徑以及其他最終可能觸發自動配置解析的操作。一旦這些完成,在大多數情況下,它們在執行時就不再需要了。

透過定義明確的環境(類路徑等),這一切都可以在構建時完成,以便只有當前環境中相關的 bean 定義被新增到 bean 工廠。在構建時執行的後置處理器將被丟棄,並替換為它們貢獻的程式碼。

有許多方法可以“提前”貢獻程式碼,從註解處理到位元組碼生成。我們選擇讓我們的新引擎生成 Java 原始碼,並在構建過程中將其貢獻給應用程式。我們相信這在開發人員體驗和最佳化機會之間取得了恰當的平衡。

這不僅能夠以熟悉且透明的方式啟用原生映象用例,而且我們還相信這將在未來為傳統的 JVM 應用程式帶來好處。例如,AOT 引擎完全獨立於原生映象,因此您可以在 JVM 上驗證應用程式的最佳化版本是否正常工作。

執行時提示 (Runtime Hints)

與 JVM 不同,執行原生映象在某些情況下需要額外的配置。例如,如果您的程式碼透過反射呼叫方法,您需要進行說明,以便在原生映象中包含必要的程式碼。或者,如果您需要讀取類的元資料(如核心容器通常在啟動時所做的那樣),您需要包含該類的位元組碼,這可能會導致更大的映象檔案。

AOT 引擎將自動推斷啟動核心容器所需的所有提示。未來我們希望這些提示能夠透過 GraalVM 本身的改進,或最佳化方面的變化而減少,使其不再必要。

測試注意事項

生成程式碼需要良好的測試故事。很容易貢獻出無法編譯的程式碼,或者即使能編譯也無法產生預期結果的程式碼。我們一直在努力開發新的測試工具來幫助我們,您可以在當前私有的 spring-core-test 模組中找到它們。

總而言之,這個基礎設施允許我們編譯程式碼(透過一個抽象層,允許我們在記憶體中提供原始碼),並 執行斷言,其中生成的程式碼可以輕鬆檢索。

假設我們已經為一些 Java 類生成了程式碼,並且我們的入口點是 MyObject

TestCompiler.forSystem().withSources(sourceFiles)
        .compile(compiled -> {
    MyObject instance = compiled.getInstance(MyObject.class);
    // invoking + assertions
});

在我們的例子中,AOT 引擎生成了一個實現 ApplicationContextInitializer 介面的入口點。這樣的基礎設施使我們能夠做到以下幾點:

  • 配置應用程式上下文以測試特定功能
  • 呼叫上下文上的 AOT 引擎
  • 使用 TestCompiler 編譯我們生成的原始碼
  • 建立一個新的應用程式上下文,並應用生成的程式碼,以檢視該功能是否按預期執行

上面關於生成程式碼的描述同樣適用於提示。我們正在開發額外的測試工具來驗證您貢獻的提示是否與執行時行為匹配。儘管這在本里程碑版本中未能實現,請訂閱 #27981 以獲取更多詳細資訊。

接下來的計劃

在下一個里程碑版本中,我們將繼續基於 Spring Native 的經驗構建核心基礎設施。曾經在 Spring Native 中的特定 Spring 專案的定製將遷移到專案中,或者透過適應引擎的開箱即用功能而變得不再必要。

Spring Framework 6.0 只是一個開始:我們打算在未來幾年內在此基礎上繼續發展,這將對 JVM 使用者產生積極影響。敬請期待!

獲取 Spring 新聞通訊

透過 Spring 新聞通訊保持聯絡

訂閱

領先一步

VMware 提供培訓和認證,助您加速進步。

瞭解更多

獲得支援

Tanzu Spring 提供 OpenJDK™、Spring 和 Apache Tomcat® 的支援和二進位制檔案,只需一份簡單的訂閱。

瞭解更多

即將舉行的活動

檢視 Spring 社群所有即將舉行的活動。

檢視所有