【Spring註解驅動開發】使用@Lazy註解實現懶載入

冰河團隊發表於2020-06-09

寫在前面

Spring在啟動時,預設會將單例項bean進行例項化,並載入到Spring容器中。也就是說,單例項bean預設在Spring容器啟動的時候建立物件,並將物件載入到Spring容器中。如果我們需要對某個bean進行延遲載入,我們該如何處理呢?此時,就需要使用到@Lazy註解了。

專案工程原始碼已經提交到GitHub:https://github.com/sunshinelyz/spring-annotation

懶載入

懶載入就是Spring容器啟動的時候,先不建立物件,在第一次使用(獲取)bean的時候,建立並使用物件,大家是不是想到了在【設計模式】專題中的單例模式呢?對單例模式不太瞭解的同學可以猛戳《淺談JAVA設計模式之——單例模式(Singleton)》,也可以檢視《設計模式彙總——你需要掌握的23種設計模式都在這兒了!》來系統學習每種設計模式。

非懶載入模式

此時,我們將PersonConfig2類的配置修改成單例項bean,如下所示。

package io.mykit.spring.plugins.register.config;

import io.mykit.spring.bean.Person;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * @author binghe
 * @version 1.0.0
 * @description 測試@Scope註解設定的作用域
 */
@Configuration
public class PersonConfig2 {
    @Bean("person")
    public Person person(){
        System.out.println("給容器中新增Person....");
        return new Person("binghe002", 18);
    }
}

接下來,在SpringBeanTest類中建立testAnnotationConfig5()方法,如下所示。

@Test
public void testAnnotationConfig5(){
    ApplicationContext context = new AnnotationConfigApplicationContext(PersonConfig2.class);
    System.out.println("IOC容器建立完成");
}

執行SpringBeanTest類中的testAnnotationConfig5()方法,輸出的結果資訊如下所示。

給容器中新增Person....
IOC容器建立完成

可以看到,單例項bean在Spring容器啟動的時候就會被建立,並載入到Spring容器中。

懶載入模式

我們在PersonConfig2的person()方法上加上@Lazy註解將Person物件設定為懶載入,如下所示。

package io.mykit.spring.plugins.register.config;

import io.mykit.spring.bean.Person;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Lazy;

/**
 * @author binghe
 * @version 1.0.0
 * @description 測試@Scope註解設定的作用域
 */
@Configuration
public class PersonConfig2 {

    @Lazy
    @Bean("person")
    public Person person(){
        System.out.println("給容器中新增Person....");
        return new Person("binghe002", 18);
    }
}

此時,我們再次執行SpringBeanTest類中的testAnnotationConfig5()方法,輸出的結果資訊如下所示。

IOC容器建立完成

可以看到,此時,只是列印出了“IOC容器建立完成”,說明此時,只建立了IOC容器,並沒有建立bean物件。

那麼,加上@Lazy註解後,bean是何時建立的呢?我們在SpringBeanTest類中的testAnnotationConfig5()方法中獲取下person物件,如下所示。

@Test
public void testAnnotationConfig5(){
    ApplicationContext context = new AnnotationConfigApplicationContext(PersonConfig2.class);
    System.out.println("IOC容器建立完成");
    Person person = (Person) context.getBean("person");
}

此時,我們再次執行SpringBeanTest類中的testAnnotationConfig5()方法,輸出的結果資訊如下所示。

IOC容器建立完成
給容器中新增Person....

說明,我們在獲取bean的時候,建立了bean物件並載入到Spring容器中。

那麼,問題又來了,只是第一次獲取bean的時候建立bean物件嗎?多次獲取會不會建立多個bean物件呢?我們再來完善下測試用例,在在SpringBeanTest類中的testAnnotationConfig5()方法中,再次獲取person物件,並比較兩次獲取的person物件是否相等,如下所示。

IOC容器建立完成
給容器中新增Person....
true

從輸出結果中,可以看出使用@Lazy註解標註後,單例項bean物件只是在第一次從Spring容器中獲取物件時建立,以後每次獲取bean物件時,直接返回建立好的物件。

總結

懶載入,也稱延時載入。僅對單例bean生效。單例bean是在Spring容器啟動的時候載入的,新增@Lazy註解後就會延遲載入,在Spring容器啟動的時候並不會載入,而是在第一次使用此bean的時候才會載入,但當你多次獲取bean的時候不會重複載入,只是在第一次獲取的時候會載入,這不是延遲載入的特性,而是單例Bean的特性。

好了,我們們今天就聊到這兒吧!別忘了給個在看和轉發,讓更多的人看到,一起學習一起進步!!

專案工程原始碼已經提交到GitHub:https://github.com/sunshinelyz/spring-annotation

寫在最後

如果覺得文章對你有點幫助,請微信搜尋並關注「 冰河技術 」微信公眾號,跟冰河學習Spring註解驅動開發。公眾號回覆“spring註解”關鍵字,領取Spring註解驅動開發核心知識圖,讓Spring註解驅動開發不再迷茫。

相關文章