給你的專案啟動提提速:Lazy Initialization

不一樣的科技宅發表於2023-05-14

前言

  在一個名為種花家的小鎮上,生活著一群熱愛程式設計的人。他們致力於構建出高效、可維護的軟體系統,而 Spring Boot 框架成為了他們的不二之選。這個小鎮上的人們每天都在用 Spring Boot 框架創造著令人矚目的應用程式。

  然而,隨著時間的推移,他們的應用程式變得越來越龐大,包含了許多不同的模組和元件。在應用程式啟動的時候,所有的 bean 都會被一次性初始化,這導致了一個令人頭疼的問題:啟動時間變得越來越長了。

  小鎮的居民們開始感到困擾。他們意識到,無論是在開發環境還是在生產環境中,啟動時間的長短都直接關係到他們的工作效率和使用者體驗。於是,他們尋找一種解決方案,希望能夠在保證應用程式正常執行的同時,減少啟動時間的開銷。

  正當大家糾結不已時,一個程式設計少俠出現了。他名叫不一樣的科技宅,他告訴大家,有一種叫做"延遲初始化"的策略,可以幫助他們解決這個問題。

  據說,延遲初始化能夠將 bean 的初始化推遲到第一次使用時進行,而不是在應用程式啟動時立即初始化。這樣一來,只有當某個 bean 真正被需要時,才會進行初始化,避免了不必要的資源消耗和時間開銷。

是什麼?

  延遲初始化(Lazy Initialization)是一種在需要時才建立或載入物件的策略,以減少啟動時間和資源消耗。在 Spring 中,延遲初始化允許將 Bean 的建立推遲到第一次訪問該 Bean 時才進行,而不是在應用程式啟動時立即建立。

有啥用?

節省資源

  當應用程式中存在大量的 bean 時,立即初始化所有 bean 可能會佔用大量的記憶體和處理時間。透過延遲初始化,只有在需要使用 bean 時才會進行初始化,可以避免不必要的資源消耗。

加快啟動時間

  延遲初始化可以減少應用程式啟動時間,因為只有在需要時才會載入和初始化 bean。對於那些在應用程式啟動時可能不會使用的較大或複雜的 bean,延遲初始化可以顯著加快啟動時間。

解決迴圈依賴

  Spring 容器可以管理 bean 之間的依賴關係。當存在迴圈依賴時,延遲初始化可以幫助解決這個問題。透過延遲初始化,Spring 容器可以在執行時逐個解析和滿足 bean 之間的依賴,而不是在初始化階段發現無法解決的迴圈依賴。

如何實現?

Spring Boot 中實現延遲初始化 Bean,可以採取以下四種方法:

  1. 對於使用註解配置的 Bean,可以在 Bean 的定義上使用 @Lazy 註解來實現延遲初始化。

示例:

@Lazy
@Component
public class MyBean {
    // Bean 的定義
}
  1. 對於使用 Java 配置類的方式,可以在 @Bean 註解上使用 @Lazy 註解,以實現延遲初始化。

示例:

@Configuration
public class AppConfig {
    @Lazy
    @Bean
    public MyBean myBean() {
        // Bean 的定義
        return new MyBean();
    }
}
  1. 對於 XML 配置的 Bean,可以在 <bean> 元素上設定 lazy-init 屬性為 true,以實現延遲初始化。

示例:

<bean id="myBean" class="com.example.MyBean" lazy-init="true" />
  1. 對於使用@ComponentScan註解,可以配置屬性lazyInit = true 實現某些包下面所有的 bean 延遲初始化。

示例:

package com.example.demo.bean;

import org.springframework.stereotype.Component;

@Component
public class MyBean {

    public MyBean() {
        System.out.println("My bean init success.");
    }
}
@SpringBootApplication
@ComponentScan(value = "com.example.demo.bean", lazyInit = true)
public class DemoApplication {

    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }

}

全域性懶載入

  上面演示案例,意味著我們只能對自己實現的 bean 進配置。但是專案中肯定會引入很多第三方的 starter,比如 redis,mq。如果想對引入的第三方庫進行配置,那就不太容易了,所以我們可以開啟全域性懶載入。

配置檔案增加下面的配置:

spring:
  main:
    lazy-initialization: true  #預設false 關閉

開啟了全域性懶載入,想要過濾某個 bean,可以透過設定 @Lazy(false) 排除。

@Component
@Lazy(false)
public class MyBean {

    public MyBean() {
        System.out.println("My bean init success.");
    }
}

還有一種是透過配置 LazyInitializationExcludeFilter 規則實現排除。

@Configuration
public class AppConfig {

    @Bean
    LazyInitializationExcludeFilter integrationLazyInitExcludeFilter() {
        return LazyInitializationExcludeFilter.forBeanTypes(MyBean.class);
    }
}

注意的點

@Lazy 註解的使用

  要確保在正確的位置使用@Lazy 註解。通常情況下,將其新增在 Bean 的定義上,例如@Component、@Service、@Repository 等註解上。這樣可以確保被標記的 Bean 在第一次使用時才會進行初始化。

依賴關係的處理

  懶載入的 Bean 可能會被其他 Bean 所依賴。在處理依賴關係時,要確保依賴的 Bean 已經被初始化或者也進行了懶載入。否則,可能會導致依賴注入失敗或出現異常。

延遲初始化帶來的影響

  懶載入雖然可以提高應用的啟動效能,但也會帶來一些影響。由於 Bean 的初始化被延遲到第一次使用,因此在初始化時可能會出現較長的延遲,對於需要立即使用的 Bean 可能會造成一定的等待時間。

記憶體消耗的控制

  懶載入雖然可以減少應用啟動時的記憶體消耗,但也需要注意對記憶體的控制。如果應用中存在大量的懶載入 Bean,並且這些 Bean 在實際使用中並不頻繁,可能會導致過多的記憶體佔用。因此,需要根據應用的具體情況,合理使用懶載入,避免過度消耗記憶體。

執行時異常的處理

  由於懶載入將 Bean 的初始化延遲到執行時,因此在初始化過程中可能會發生異常。要確保適當地處理這些異常,以防止應用的崩潰或不可預料的行為。

總結

  懶載入是一種延遲載入的技術,用於在需要時才載入資源,而不是在應用啟動時載入所有資源。在 Spring Boot 框架中,有兩種方式可以實現懶載入:Spring 懶載入和全域性懶載入。無論是懶載入還是全域性懶載入,它們都能提升應用的效能和效率,避免不必要的資源載入。

  在使用 Spring 懶載入需要注意正確的註解使用、處理依賴關係、延遲初始化帶來的影響、記憶體消耗控制和異常處理等方面。合理地使用可以提高應用效能,但也需要綜合考慮應用的需求和場景,以確保有效性和穩定性。

結尾

  如果覺得對你有幫助,可以多多評論,多多點贊哦,也可以到我的主頁看看,說不定有你喜歡的文章,也可以隨手點個關注哦,謝謝。

  我是不一樣的科技宅,每天進步一點點,體驗不一樣的生活。我們下期見!

相關文章