成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

SpringBoot.3中的aot.factories到底有什么用?和以前的spring.factories一樣嗎?

開發 前端
在探索 aot.factories? 和 spring.factories 的過程中,我們不僅揭示了這兩個文件的本質差異,還深入探討了它們在 Spring Boot 3 中的作用及其應用場景。

首先,我們來澄清一下 aot.factories 和 spring.factories 之間的區別。這兩個文件不僅名稱不同,而且在功能上也存在顯著差異。接下來,我們將深入探討這兩個文件的具體作用以及它們各自的應用場景。讓我們一起來揭開它們的神秘面紗吧!

在我們上一次討論 Spring Boot 3 版本時,我們關注了它的加載機制并注意到了一些小的變化。嚴格來說,這些變化主要體現在文件名稱的調整上:原本的 META-INF/spring.factories 文件已經遷移至新的位置,即 META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports。

想要了解更多詳細信息,歡迎查閱這篇文章:https://www.cnblogs.com/guoxiaoyu/p/18384642

問題來了

要深入了解 Spring Boot 的加載機制,首先需要認識到每個第三方依賴包實際上都包含自己獨特的 META-INF/spring.factories 文件。正如圖中所示。

這些文件在應用程序啟動時扮演著重要的角色,它們定義了自動配置的類和其他相關設置,幫助 Spring Boot 在運行時自動識別和加載相應的配置。

圖片圖片

然而,當我們試圖查看某個第三方依賴包時,可能會發現找不到相應的 META-INF/spring.factories 文件,甚至沒有 *.imports 文件,這時該怎么辦呢?不要慌張!并不是所有的項目都具備自動配置功能。例如,ZhiPuAiAutoConfiguration 的自動配置實際上已經包含在 Spring Boot 的核心庫中。

@AutoConfiguration(after = { RestClientAutoConfiguration.class, SpringAiRetryAutoConfiguration.class })
@ConditionalOnClass(ZhiPuAiApi.class)
@EnableConfigurationProperties({ ZhiPuAiConnectionProperties.class, ZhiPuAiChatProperties.class,
        ZhiPuAiEmbeddingProperties.class, ZhiPuAiImageProperties.class })
public class ZhiPuAiAutoConfiguration {
}

可以簡單理解為,一旦你引用了相應的依賴包,它們的配置便會立即生效。然而,在查找配置的 *.imports 文件時,我發現了一個有趣的現象:許多依賴包下也存在 aot.factories 文件。這是用來做什么的呢?考慮到 Spring Boot 自身也包含此類文件,這表明這個概念并非無的放矢。

因此,帶著這個疑問,我決定深入探究其背后的機制與作用。

一探究竟

經過了一番 AI 問答和上網搜索,我大致了解了 aot.factories 文件的用途:它實際上是為打包和編譯服務的。這個文件可以幫助將 Java 項目打包成可執行的 EXE 文件(在 Windows 系統下,其他操作系統則有不同的打包方式),這樣就無需依賴 Java 運行環境即可直接運行。不過,這與 Spring Boot 的自動配置機制并沒有直接關系。

那么,為什么會發明這樣的東西呢?我知道你很著急,但是你先別著急!聽我一點一點講,你就更明白了!

Java當前痛點

有過 Java 開發經驗的朋友們應該都知道,以前的 Java 應用通常都是單體架構,這意味著啟動一個項目往往需要耗費幾分鐘的時間,尤其是大型項目,啟動時間更是讓人頭疼。因此,隨著技術的發展,微服務架構應運而生,不僅顯著縮短了啟動時間,而且將業務邏輯進行了合理的切分。

然而,微服務架構也并非沒有缺點。盡管啟動速度更快,項目在啟動后往往無法立即達到最佳的運轉狀態,也就是說,應用需要一段時間才能進入高效的運行峰值。

因為 Java 的底層通常使用的是 HotSpot 虛擬機,HotSpot 的運行機制是將常用的代碼部分編譯為本地(即原生)代碼。這意味著在程序啟動之初,HotSpot 并不知道哪些代碼會成為“熱點”代碼,因此無法立即將這些代碼轉換為機器能夠直接理解和執行的形式。

在這個過程中,HotSpot 會不斷分析和監測代碼的執行情況,以快速識別出哪些部分是頻繁被調用的。只有在識別出熱點代碼并將其編譯為本地代碼之后,我們的項目才能實現最佳的吞吐量。

要想讓 Java 像 Python 那樣實現瞬時啟動,幾乎是不可能的。這一現象使得 Java 在很多情況下更適合用于企業級服務,主要原因在于其所追求的穩定性和可靠性。在企業環境中,系統的穩定性往往是首要考慮的因素。

然而,Java 也面臨著一系列挑戰,這些挑戰在云計算時代尤為突出。

云時代

以 Serverless 為例,Serverless 是一種在云計算環境中日益成為主流的部署模式。它通過將基礎設施的管理和運維任務抽象化,使開發者能夠更加專注于業務邏輯的實現,而不必過多關注底層的資源配置和管理。

圖片圖片

我就不提以前那種需要自己部署物理機的老年代的情況了。如今,絕大多數公司都已經采用了 Kubernetes(K8s)作為集群管理的解決方案。在各大云服務提供商處購買服務器后,企業通常會自行管理其集群服務。運維團隊則負責監控和優化資源配置,及時進行擴展以滿足需求。

此外,隨著技術的發展,Server Mesh 和邊車模式也逐漸興起,這些都是值得深入了解的概念。歸根結底,這些改進的目的就是為了顯著節省公司內部的開發時間,從而讓團隊能夠更專注于核心業務。

目前的 Serverless 架構顯著提高了資源利用的效率,因為所有的基礎設施管理工作都由云服務提供商負責。實際上,云廠商的基礎設施本身并沒有發生根本變化,變化的主要是架構設計,使得客戶的使用體驗更加便捷和高效。在這種模式下,無論是運維人員還是開發人員,都只需關注函數的部署,而無需深入了解服務器的細節信息。

開發者不再需要關心函數的運行方式、底層有多少容器或服務器在支撐這些服務。對他們而言,這一切都被抽象化為一個簡單的接口,只需確保參數對接得當即可。

但是,你敢用 Java 來部署 Serverless 函數嗎?當系統的吞吐量急劇上升,需要迅速啟動一個新節點來支撐額外的負載時,這位 Java 大哥可能還在忙著啟動或者進行預熱,這可真是耽誤事啊!所以Java作為牛馬屆的老大哥怎么可能會愿意當小弟?

GraalVM 簡介

如果你還不熟悉 GraalVM,但一定聽說過 OpenJDK。實際上,它們都是完整的 JDK 發行版本,能夠運行任何面向 JVM 的語言開發的應用。不過,GraalVM 不僅限于此,它還提供了一項獨特的功能——Native Image 打包技術。這項技術的強大之處在于,它能夠將應用程序打包成可以獨立運行的二進制文件,這些文件是自包含的,完全可以脫離 JVM 環境運行。

換句話說,GraalVM 允許你創建類似于常見的可執行文件(如 .exe 文件)的應用程序,這使得部署和分發變得更加簡便和靈活。

圖片圖片

如上圖所示,GraalVM 編譯器提供了兩種模式:即時編譯(JIT)和提前編譯(AOT)。AOT全稱為Ahead-of-Time Processing。

對于 JIT 模式,我們都知道,Java 類在編譯后會生成 .class 格式的文件,這些文件是 JVM 可以識別的字節碼。在 Java 應用運行的過程中,JIT 編譯器會將一些熱點路徑上的字節碼動態編譯為機器碼,以實現更快的執行速度。這種方法充分利用了運行時信息,能夠根據實際的執行情況進行優化,從而提高了性能。

而對于 AOT 模式,GraalVM 則在編譯期間就將字節碼轉換為機器碼,完全省去了運行時對 JVM 的依賴。由于省去了 JVM 加載和字節碼運行期預熱的時間,AOT 編譯和打包的程序具有非常高的運行時效率。這意味著在啟動時,應用程序可以幾乎瞬間響應,極大地提高了處理請求的能力。

那么,這種 AOT 編譯到底有多快?它是否會成為 Serverless 函數的一種常用方案,超越 Python 等其他語言的應用呢?為了驗證其性能優勢,我們可以進行實際測試。

安裝GraalVM

我們大家基本上都在本地安裝了 IntelliJ IDEA 開發工具,使用起來非常方便。在這里,我們可以直接通過 IDEA 的內置功能下載 GraalVM,省去了在官方網站上尋找和下載的時間。只需簡單幾步,我們就可以快速獲取到最新的 GraalVM 版本,隨時準備進行開發。

下載完成后,我們只需配置項目的 JDK 為 GraalVM。由于我目前使用的是 JDK 17,因此需要選擇與之兼容的 GraalVM 17 版本。這種配置過程相對簡單,只需在項目設置中更改 JDK 路徑即可。

圖片圖片

我們將繼續使用之前研究過的 Spring AI 項目,在此基礎上,我們需要添加一些相關的 Spring Boot 插件。

<plugin>
    <groupId>org.graalvm.buildtools</groupId>
    <artifactId>native-maven-plugin</artifactId>
</plugin>

在我們順利完成所有配置后,準備進行編譯時,卻意外地遇到了錯誤提示,顯示 JAVA_HOME 指向的是我們原本的 JDK 1.8。這一問題的出現主要是由于其中某個工具并不依賴于 IntelliJ IDEA 的啟動變量,而是直接讀取了 JAVA_HOME 的環境變量。

為了解決這個問題,我們需要確保 JAVA_HOME 環境變量正確指向我們新安裝的 GraalVM 版本。因此,我們必須在本地系統中下載并安裝 GraalVM,確保其版本與我們項目中所需的 JDK 版本相匹配。

首先我們找到官網:https://www.graalvm.org/downloads/

圖片圖片

因為我是windows版本,所以自己請選擇好相應的操作系統。等待下載完畢,解壓完成后,將配置環境變量指向改目錄后重啟生效,再次編譯即可。

運行后,還是報錯如下:Error: Please specify class (or/) containing the main entry point method. (see --help)

內容就是找不到啟動類的意思,所以需要加一些配置。找了半天修改如下,切記前后順序別變,否則還是會有點問題。

<build>
        <plugins>
            <plugin>
                <groupId>org.graalvm.buildtools</groupId>
                <artifactId>native-maven-plugin</artifactId>
                <configuration>
                    <!-- imageName用于設置生成的二進制文件名稱 -->
                    <imageName>${project.artifactId}</imageName>
                    <!-- mainClass用于指定main方法類路徑 -->
                    <mainClass>com.example.demo.DemoApplication</mainClass>
                    <buildArgs>
                        --no-fallback
                    </buildArgs>
                </configuration>
                <executions>
                    <execution>
                        <id>build-native</id>
                        <goals>
                            <goal>compile-no-fork</goal>
                        </goals>
                        <phase>package</phase>
                    </execution>
                </executions>
            </plugin>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <excludes>
                        <exclude>
                            <groupId>org.projectlombok</groupId>
                            <artifactId>lombok</artifactId>
                        </exclude>
                    </excludes>
                </configuration>
            </plugin>
        </plugins>
    </build>

接下來,我們將繼續使用常用的 Maven 命令,如 mvn clean package,來進行項目的打包。這個過程可能會顯得有些漫長,尤其是與以前相比,打包速度似乎下降了不止一個級別。這次,我的打包過程持續了大約十分鐘,這確實比我之前的體驗慢了不少。

圖片圖片

然后非常激動的點擊了生成好的demo.exe文件,結果還是在報錯:

.   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/

 :: Spring Boot ::                (v3.3.1)

Application run failed
org.springframework.boot.AotInitializerNotFoundException: Startup with AOT mode enabled failed: AOT initializer com.example.demo.DemoApplication__ApplicationContextInitializer could not be found
        at org.springframework.boot.SpringApplication.addAotGeneratedInitializerIfNecessary(SpringApplication.java:443)
        at org.springframework.boot.SpringApplication.prepareContext(SpringApplication.java:400)
        at org.springframework.boot.SpringApplication.run(SpringApplication.java:334)
        at org.springframework.boot.SpringApplication.run(SpringApplication.java:1363)
        at org.springframework.boot.SpringApplication.run(SpringApplication.java:1352)
        at com.example.demo.DemoApplication.main(DemoApplication.java:10)

然后經過仔細查詢,需要指定profile為native,因為之前打的包沒有Aot信息。

圖片圖片

好的,又經歷了15分鐘打包完畢,這次,我們終于成功了,我們可以直觀的看下AOT方式打包后的啟動時間與jar包方式的啟動時間對比。簡直是天壤之別。

圖片圖片

哦?確實,現在的啟動時間已經縮短到毫秒級別,真令人驚訝!通過 GraalVM 的 Native Image 技術,我們不僅實現了 Java 項目的快速啟動,還有效去除了傳統 Java 應用中的預熱時間。這一切看似都非常理想,然而,問題也隨之而來。

GraalVM 缺點

說完了 GraalVM 能解決 Java 原來的問題后,我們也必須認識到,它并非沒有缺點。如果沒有這些不足,大家對 GraalVM 的了解程度肯定會超過對 OpenJDK 的熟悉度。畢竟,既然它如此出色,為什么大多數人卻沒有廣泛使用呢?

首先,兼容性問題是一個顯著的挑戰。許多老舊版本的 JDK 項目根本無法與 GraalVM 兼容,這無疑限制了大部分企業的使用范圍。對于那些依賴于較舊 JDK 的企業而言,遷移到 GraalVM 可能需要耗費大量時間和資源,甚至面臨重構代碼的風險。

其次,即便是使用新版本 JDK 的項目,開發者們也往往對使用 GraalVM 感到猶豫。原因在于,GraalVM 對某些動態特性的支持相對較弱。例如,反射機制、資源加載、序列化以及動態代理等功能的限制,可能會對現有代碼的運行產生重大影響。這些動態行為在許多應用程序中都是核心部分,任何對它們的削弱都可能導致功能缺失或性能問題。

有人可能會產生疑問:Spring 框架本身依賴于工廠模式和各種動態代理功能,若 GraalVM 不支持這些高級特性,豈不是意味著 Spring 的運行將受到致命影響?如果動態代理無法正常使用,Spring 的許多核心功能將會受到制約,那剛才提到的打包成功又是怎么回事呢?

實際上,這一切的背后得益于 GraalVM 提供的 AOT(Ahead-of-Time)元數據文件功能。這個特性使得開發者能夠在編譯階段明確哪些類和方法將會使用到動態代理,GraalVM 會在編譯時將這些信息整合到最終的可執行文件中。

RuntimeHints與aot.factories

GraalVM 的 API —— RuntimeHints 負責在運行時收集反射、資源加載、序列化和 JDK 代理等功能的需求。這一特性為我們理解 GraalVM 如何支持動態特性提供了重要線索。實際上,大家在這里就可以猜到 aot.factories 文件的作用。沒錯,這個文件的存在正是為了在 GraalVM 編譯時,確保能夠加載 Spring 框架所需的 JDK 代理相關需求。我們看下文件:

org.springframework.aot.hint.RuntimeHintsRegistrar=\
org.springframework.boot.autoconfigure.freemarker.FreeMarkerTemplateAvailabilityProvider.FreeMarkerTemplateAvailabilityRuntimeHints,\
org.springframework.boot.autoconfigure.groovy.template.GroovyTemplateAvailabilityProvider.GroovyTemplateAvailabilityRuntimeHints,\
org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration.JacksonAutoConfigurationRuntimeHints,\
org.springframework.boot.autoconfigure.template.TemplateRuntimeHints

org.springframework.beans.factory.aot.BeanFactoryInitializatinotallow=\
org.springframework.boot.autoconfigure.logging.ConditionEvaluationReportLoggingProcessor

org.springframework.beans.factory.aot.BeanRegistratinotallow=\
org.springframework.boot.autoconfigure.flyway.ResourceProviderCustomizerBeanRegistrationAotProcessor

org.springframework.beans.factory.aot.BeanRegistratinotallow=\
org.springframework.boot.autoconfigure.SharedMetadataReaderFactoryContextInitializer

我們可以注意到 RuntimeHintsRegistrar 的存在,它的主要作用是識別并加載所有實現了相關接口的類,從而進行解析和處理。需要強調的是,GraalVM 默認并不會自動查找 aot.factories 文件,因為這屬于 Spring 的特定機制。這就意味著,如果沒有顯式的指引,GraalVM 是無法主動識別和利用這些動態特性。

在 RuntimeHintsRegistrar 下面,我們還可以看到許多 AotProcessor 的實現。這個結構和我們之前討論的 beanFactoryProcessor 有些相似,但這里我們不深入探討具體的細節。今天我們只聚焦于表面現象,以便理解其基本功能。

Spring 實際上已經為我們解決了加載相關信息的問題,使得動態特性可以在編譯時得到適當處理。然而,這并不意味著一切都已經準備就緒。第三方組件同樣需要提供相應的實現,以確保與 Spring 的兼容性。如果你的依賴庫使用了某些高級功能,但沒有實現 Spring 的 aot.factories 掃描機制,那么這些功能在編譯后將無法生效。

因此,仍然有許多工作需要進行,以確保整個生態系統的兼容性和功能性。

總結

在探索 aot.factories 和 spring.factories 的過程中,我們不僅揭示了這兩個文件的本質差異,還深入探討了它們在 Spring Boot 3 中的作用及其應用場景。這一探索之旅引領我們進入了現代 Java 應用開發的前沿,尤其是在 Serverless 和微服務架構的背景下。隨著云計算的發展,應用程序的性能與啟動速度已成為開發者的核心關注點。在此背景下,GraalVM 的出現提供了一種新穎的解決方案,通過其 Native Image 功能,Java 應用的啟動時間得以大幅度縮短,這為開發者們帶來了巨大的便利。

然而,我們也意識到,雖然 GraalVM 提供了諸多優勢,但它并非沒有挑戰。兼容性問題仍然是一個主要障礙,許多老舊 JDK 項目可能難以遷移到新平臺。此外,某些動態特性在 GraalVM 中的支持仍顯不足,這可能會影響到開發者在使用 Spring 框架時的靈活性與功能實現。尤其是在復雜的企業應用中,這種影響可能更加明顯。

借助 Spring 框架與 GraalVM 的結合,開發者能夠享受更快的應用啟動速度和更好的資源利用率,但同時也要做好充分的準備,以應對兼容性帶來的潛在問題。這意味著,隨著新技術的不斷涌現,我們需要不斷地學習、適應和優化自己的開發流程。

責任編輯:武曉燕 來源: 靈墨AI探索室
相關推薦

2025-04-27 03:00:00

Spring技術接口

2025-04-01 08:08:29

2022-05-27 08:44:09

springStarter配置

2025-04-03 08:21:18

2023-01-13 16:57:50

SpringBoot配置核心

2022-07-29 08:25:02

volatileC語言原子

2023-09-07 23:06:07

2019-10-14 10:29:42

Java消息隊列

2020-04-30 09:41:04

數據中臺CIO觀點

2020-10-20 09:57:04

量子計算人工智能技術

2024-02-28 16:18:41

2025-06-18 07:32:16

SpringJar動態加載

2022-05-24 12:57:49

函數代碼Java

2021-04-28 09:55:52

JavaLock接口并發編程

2019-05-16 10:30:49

JavaTCP協議

2021-05-11 10:44:51

飛行模式通信設備通信干擾

2009-08-20 16:08:31

FCC美國寬帶計劃

2023-11-08 08:47:34

Spring容器管理

2022-10-27 19:32:20

切片golang數組

2024-02-19 00:00:00

Python?starmap函數
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: www国产成人免费观看视频 | 亚州国产| 精品久久九 | 日本精品一区二区三区在线观看视频 | а√中文在线8 | 亚洲综合资源 | 国产精品激情小视频 | 可以免费看的毛片 | 永久免费av | 狠狠干综合视频 | 麻豆精品一区二区三区在线观看 | 国产精品一区在线观看 | 日本欧美在线 | 久久免费精品 | av三级在线观看 | 成人精品一区 | 秋霞电影一区二区三区 | 一区二区三区日韩精品 | 久久精品国产精品青草 | 欧美伊人影院 | 日本视频一区二区 | 欧美中文在线 | 毛片毛片毛片毛片毛片 | 亚洲永久在线 | 亚洲精品视频二区 | 日韩精品1区2区3区 爱爱综合网 | 成年网站在线观看 | 日本欧美国产在线 | 在线看av网址 | 亚洲综合色视频在线观看 | 福利一区在线观看 | 99精品国产一区二区青青牛奶 | 在线视频一区二区 | 81精品国产乱码久久久久久 | 国产欧美在线一区二区 | 久久99久久99精品免视看婷婷 | 成人国产精品免费观看 | 日日射影院 | 色综合一区二区 | 激情亚洲| 免费一级片 |