領先一步
VMware 提供培訓和認證,以加速您的進展。
瞭解更多最近發佈的 Spring Boot 2.2 第一個里程碑版本引入了對延遲初始化的支援。這篇文章描述了新的功能,並解釋了如何以及何時啟用它。
Spring Framework 自其原始碼 11 年前遷移到 Git 之前,就已支援 Bean 的延遲初始化。預設情況下,當重新整理應用程式上下文時,上下文中的每個 Bean 都會被建立,並且其依賴項也會被注入。 相反地,當 Bean 定義被設定為延遲初始化時,它將不會被建立,並且其依賴項也不會被注入,直到它被需要時才會。
如果您樂於親自動手並編寫 BeanFactoryPostProcessor
,則可以在任何版本的 Spring Boot 中啟用延遲初始化。Spring Boot 2.2 通過引入一個新的屬性 spring.main.lazy-initialization
使其更容易(在 SpringApplication
和 SpringApplicationBuilder
上也有等效的方法)。當設定為 true
時,應用程式中的 Bean 定義將被設定為使用延遲初始化。
延遲初始化可以顯著減少啟動時間,因為在應用程式啟動期間加載的類別更少,並且建立的 Bean 也更少。例如,一個使用 Actuator 和 Spring Security 的小型 Web 應用程式通常在 2500 毫秒內啟動,啟用延遲初始化後將在 2000 毫秒內啟動。確切的改進將因應用程式而異,具體取決於其 Bean 依賴圖的結構。
Spring Boot 的 DevTools 已經顯著提高了開發人員的生產力。 每次想要試用變更時,不必重新啟動 JVM 和應用程式,DevTools 可以在同一個 JVM 中熱重新啟動應用程式。 熱重新啟動的一個顯著優點是,它使 JIT 更有機會優化啟動應用程式所涉及的程式碼。 幾次重新啟動後,原始的 2500 毫秒時間減少了近 80%,接近 500 毫秒。 透過延遲初始化,我們可以做得更好。設定 spring.main.lazy-initialization
可以看到我們的應用程式直接在 IDE 中以 400 毫秒重新啟動。
正如我們在上面看到的,啟用延遲初始化可以大幅縮短啟動時間。 您可能會想一直啟用它,或者想知道為什麼我們沒有決定預設啟用它。 延遲初始化有一些缺點,這意味著我們認為在您確定這樣做有意義後,選擇加入會更好。
由於類別不再被加載,並且 Bean 不再被建立直到它們被需要時,延遲初始化可能會掩蓋一個以前會在啟動時識別出的問題。 這些問題可能包括找不到類別定義錯誤、記憶體不足錯誤以及由於配置錯誤而導致的失敗。
在 Web 應用程式中,延遲初始化可能會導致觸發 Bean 初始化的 HTTP 請求的延遲增加。 這通常只會是第一個請求,但可能會對負載平衡和自動縮放產生不利影響。
如果您不確定延遲初始化對應用程式有什麼影響,或者您想驗證另一個框架的行為是否符合您的需求並符合他們的聲明,使用偵錯工具可能會很有用。 通過在 Bean 的建構子中放置一個中斷點,您可以查看它何時被初始化。 例如,在啟用延遲初始化的 Spring Boot Web 應用程式中,您會看到 @Controller
Bean 直到第一個請求傳送到 Spring MVC 的 DispatcherServlet
或 Spring WebFlux 的 DispatcherHandler
時才會被建立。
正如我們在上面看到的,延遲初始化可以在啟動時間方面提供顯著的改進,但也有一些值得注意的缺點,因此謹慎地啟用它非常重要。
在開發過程中,延遲初始化可以帶來極大的好處,並且幾乎沒有任何缺點。 當您在迭代應用程式時,延遲初始化和 DevTools 熱重新啟動提供的縮短啟動時間可以顯著提高您的生產力。
另一個可以從延遲初始化中受益的領域是應用程式的整合測試。 您可能已經在使用 Spring Boot 的測試切片,通過限制在某些類型的測試中初始化的 Bean 的數量來減少測試執行時間。 延遲初始化提供了一種替代機制來實現類似的最終結果。 如果您無法構建應用程式,使其適用於測試切片,或者如果特定類型的測試沒有可用的切片,則啟用延遲初始化將限制初始化為測試所需的 Bean。 這將減少測試執行時間,尤其是在開發過程中單獨執行測試時。
最後,您可能需要考慮在生產環境中啟用延遲初始化。 如果這樣做,應謹慎行事。 對於 Web 應用程式,容器編排可能會受益於能夠更快響應的 /health
端點,但您也需要注意當首次請求傳送到應用程式自身的端點之一時可能導致的延遲增加。 您還應注意在禁用延遲初始化的情況下調整應用程式的 JVM 大小,以避免一旦所有元件都被使用後出現任何不必要的記憶體不足錯誤。