使用lazyInit縮短Spring Boot啟動時間

banq發表於2018-08-19
雖然Spring Boot DevTools提供的快速重啟有助於庫類載入,但並不能解決Spring Boot應用啟動時間長的問題。在本文中,我們將看看如何使用SpringBoot的懶載入屬性提升我們應用程式的啟動時間。

起初,無論你選擇哪種嵌入式伺服器Tomcat或Jetty,全新輕裝上陣的Spring Boot Web應用都會快速啟動。隨著新功能和依賴項不斷加入,應用程變得越來越重,啟動時間也越來越長。從建立與資料庫的連線,透過網路從整合端點獲取資料,或從本地資源載入以及解析50兆位元組的XML檔案,你的應用在啟動後就非常繁忙,有時超過十幾分鍾或更長時間。

所有繁重工作在都放在啟動時完成,這樣應用在執行時能有很好的效能,使用者操作我們的應用時就無需停頓等待或遇到糟糕的效能,所有資源都已準備好並進行快取,因此在真正請求時可立即使用。

另一方面,作為開發人員,我們也不喜歡等待並浪費時間對啟動日誌進行非生產性檢查。這裡有一個簡單的解決方案可以應用於任何專案,以減輕一些等待啟動的痛苦並改善你的開發體驗。

想象一下,如果你有一個Spring bean來載入和快取某些資源的值,資源可能是遠端Web服務或需要對映到模型物件的本地CSV檔案的陣列,在生產環境中,在啟動時需要做這樣事情。

但是,如果你在本地執行應用程式,則很可能並不總是需要此資源,而只是在使用依賴於它的功能時才需要此資源。在下面的示例中,我們使用sleep()方法人為代表應用的緩慢啟動。

@Component
class ResourceLoader {
 
    private List<Term> resources;
 
    @PostConstruct
    void initHeavyLoading() throws InterruptedException {
        log.info("Loading start");
        // time-consuming execution
        Thread.sleep(10_000);
        resources = loadResources();
        log.info("Loading end");
    }
     
    // …
 
}
<p class="indent">


Spring Boot可以進行有助於相關針對專案的設定,包括最常見的預設設定和隨時可用的配置,這無疑是很棒的,因為它節省了寶貴的時間 然而,對於框架的新手來說,可能不熟悉這些配置。

你可能知道@SpringBootApplication本身並沒有做任何事情。它預設組合三個註釋@Configuration,@EnableAutoConfiguration和@ComponentScan,但是,並不是每個人都知道@ComponentScan註釋有一個特別有用的屬性: lazyInit。

LazyInit是一個布林標誌,指示容器在啟動時或第一次訪問容器時是否應該立即地建立所有發現的bean。預設情況下,該標誌設定為false,這在生產中很好,但在本地計算機上開發應用程式時不一定。

我們想要實現的是僅在本地開發環境中啟用bean延遲載入,並在生產環境實現立即初始化載入。

 
@SpringBootApplication
public class LazyApplication {
 
    public static void main(String[] args) {
        SpringApplication.run(LazyApplication.class, args);
    }
 
    @Configuration
    @Profile("local")
    @ComponentScan(lazyInit = true)
    static class LocalConfig {
    }
 
}
<p class="indent">

上面的示例提供了一個普通的Spring Boot主入口應用類,它包含一個靜態內部配置類,其中惰性初始化設定為true。該類使用@Profile進行註釋,以便僅在啟用本地配置檔案時才啟用它。

原理很簡單,如果啟用了本地配置檔案,則LocalConfig類中@ComponentScan中的lazyInit將覆蓋主類上@SpringBootApplication批註提供的預設值。如果取消啟用本地配置檔案,則忽略LocalConfig類並使用預設值。

最後,你需要啟用計算機上的本地配置檔案,有幾個選項可供選擇。最簡單的方法是在你的作業系統中永久設定spring.profiles.active環境變數,或者在每次啟動應用程式之前用你喜歡的IDE自動設定。在IntelliJ中,可以在專案主類的Run / Debug配置中指定它。

或者,如果你有一個用於本地開發的單獨Maven配置檔案,並且你使用Spring Boot Maven外掛來執行你的應用程式,則可以在pom.xml中配置活動配置檔案。

你可以在GitHub儲存庫中測試示例專案的功能。首先,執行沒有本地配置檔案的應用程式,以檢視是否執行了ResourceLoader類的初始化。然後設定配置檔案並重新啟動應用程式。

禁用所選bean的延遲初始化
儘管@ComponentScan(lazyInit = true)會影響所有已掃描的bean,但你可以僅針對所選元件覆蓋此行為並立即初始化它們。該@Lazy註釋具有幾個不同的用途,可以應用於互補的景或替代解決方案。如果你有興趣在提高你的Spring應用程式的啟動速度,你一定要熟悉與@Lazy註釋。

瞭解你的工具集
在你使用JRebel之類的商業執行時位元組程式碼操作工具之前,有必要驗證簡單的延遲初始化是否不足以在開發環境中提高工作舒適度。Spring是一個高度精心設計的框架,它仍在不斷髮展。毫不奇怪,不瞭解一些有用的功能是常有的事。

雖然有些人可能會認為對框架內部的熟悉與一般使用框架的想法相矛盾,但這篇文章表明,至少學習基礎知識可能是有益的。

Faster Spring Boot startup | Java & Web developmen

[該貼被banq於2018-08-19 08:50修改過]

相關文章