SpringBoot項(xiàng)目速度提升之延遲初始化(Lazy Initialization)詳解
前言
在一個(gè)名為種花家的小鎮(zhèn)上,生活著一群熱愛(ài)編程的人。他們致力于構(gòu)建出高效、可維護(hù)的軟件系統(tǒng),而 Spring Boot 框架成為了他們的不二之選。這個(gè)小鎮(zhèn)上的人們每天都在用 Spring Boot 框架創(chuàng)造著令人矚目的應(yīng)用程序。
然而,隨著時(shí)間的推移,他們的應(yīng)用程序變得越來(lái)越龐大,包含了許多不同的模塊和組件。在應(yīng)用程序啟動(dòng)的時(shí)候,所有的 bean 都會(huì)被一次性初始化,這導(dǎo)致了一個(gè)令人頭疼的問(wèn)題:?jiǎn)?dòng)時(shí)間變得越來(lái)越長(zhǎng)了。
小鎮(zhèn)的居民們開(kāi)始感到困擾。他們意識(shí)到,無(wú)論是在開(kāi)發(fā)環(huán)境還是在生產(chǎn)環(huán)境中,啟動(dòng)時(shí)間的長(zhǎng)短都直接關(guān)系到他們的工作效率和用戶(hù)體驗(yàn)。于是,他們尋找一種解決方案,希望能夠在保證應(yīng)用程序正常運(yùn)行的同時(shí),減少啟動(dòng)時(shí)間的開(kāi)銷(xiāo)。
正當(dāng)大家糾結(jié)不已時(shí),一個(gè)編程少俠出現(xiàn)了。他名叫不一樣的科技宅,他告訴大家,有一種叫做"延遲初始化"的策略,可以幫助他們解決這個(gè)問(wèn)題。
據(jù)說(shuō),延遲初始化能夠?qū)?bean 的初始化推遲到第一次使用時(shí)進(jìn)行,而不是在應(yīng)用程序啟動(dòng)時(shí)立即初始化。這樣一來(lái),只有當(dāng)某個(gè) bean 真正被需要時(shí),才會(huì)進(jìn)行初始化,避免了不必要的資源消耗和時(shí)間開(kāi)銷(xiāo)。
是什么?
延遲初始化(Lazy Initialization)是一種在需要時(shí)才創(chuàng)建或加載對(duì)象的策略,以減少啟動(dòng)時(shí)間和資源消耗。在 Spring 中,延遲初始化允許將 Bean 的創(chuàng)建推遲到第一次訪(fǎng)問(wèn)該 Bean 時(shí)才進(jìn)行,而不是在應(yīng)用程序啟動(dòng)時(shí)立即創(chuàng)建。
有啥用?
節(jié)省資源
當(dāng)應(yīng)用程序中存在大量的 bean 時(shí),立即初始化所有 bean 可能會(huì)占用大量的內(nèi)存和處理時(shí)間。通過(guò)延遲初始化,只有在需要使用 bean 時(shí)才會(huì)進(jìn)行初始化,可以避免不必要的資源消耗。
加快啟動(dòng)時(shí)間
延遲初始化可以減少應(yīng)用程序啟動(dòng)時(shí)間,因?yàn)橹挥性谛枰獣r(shí)才會(huì)加載和初始化 bean。對(duì)于那些在應(yīng)用程序啟動(dòng)時(shí)可能不會(huì)使用的較大或復(fù)雜的 bean,延遲初始化可以顯著加快啟動(dòng)時(shí)間。
解決循環(huán)依賴(lài)
Spring 容器可以管理 bean 之間的依賴(lài)關(guān)系。當(dāng)存在循環(huán)依賴(lài)時(shí),延遲初始化可以幫助解決這個(gè)問(wèn)題。通過(guò)延遲初始化,Spring 容器可以在運(yùn)行時(shí)逐個(gè)解析和滿(mǎn)足 bean 之間的依賴(lài),而不是在初始化階段發(fā)現(xiàn)無(wú)法解決的循環(huán)依賴(lài)。
如何實(shí)現(xiàn)?
Spring Boot 中實(shí)現(xiàn)延遲初始化 Bean,可以采取以下四種方法:
1.對(duì)于使用注解配置的 Bean,可以在 Bean 的定義上使用 @Lazy
注解來(lái)實(shí)現(xiàn)延遲初始化。
示例:
@Lazy @Component public class MyBean { // Bean 的定義 }
2.對(duì)于使用 Java 配置類(lèi)的方式,可以在 @Bean
注解上使用 @Lazy
注解,以實(shí)現(xiàn)延遲初始化。
示例:
@Configuration public class AppConfig { @Lazy @Bean public MyBean myBean() { // Bean 的定義 return new MyBean(); } }
3.對(duì)于 XML 配置的 Bean,可以在 <bean>
元素上設(shè)置 lazy-init
屬性為 true
,以實(shí)現(xiàn)延遲初始化。
示例:
<bean id="myBean" class="com.example.MyBean" lazy-init="true" />
4.對(duì)于使用@ComponentScan
注解,可以配置屬性lazyInit = true
實(shí)現(xiàn)某些包下面所有的 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); } }
全局懶加載
上面演示案例,意味著我們只能對(duì)自己實(shí)現(xiàn)的 bean 進(jìn)配置。但是項(xiàng)目中肯定會(huì)引入很多第三方的 starter,比如 redis,mq。如果想對(duì)引入的第三方庫(kù)進(jìn)行配置,那就不太容易了,所以我們可以開(kāi)啟全局懶加載。
配置文件增加下面的配置:
spring: main: lazy-initialization: true #默認(rèn)false 關(guān)閉
開(kāi)啟了全局懶加載,想要過(guò)濾某個(gè) bean,可以通過(guò)設(shè)置 @Lazy(false) 排除。
@Component @Lazy(false) public class MyBean { public MyBean() { System.out.println("My bean init success."); } }
還有一種是通過(guò)配置 LazyInitializationExcludeFilter 規(guī)則實(shí)現(xiàn)排除。
@Configuration public class AppConfig { @Bean LazyInitializationExcludeFilter integrationLazyInitExcludeFilter() { return LazyInitializationExcludeFilter.forBeanTypes(MyBean.class); } }
注意的點(diǎn)
@Lazy 注解的使用
要確保在正確的位置使用@Lazy 注解。通常情況下,將其添加在 Bean 的定義上,例如@Component、@Service、@Repository 等注解上。這樣可以確保被標(biāo)記的 Bean 在第一次使用時(shí)才會(huì)進(jìn)行初始化。
依賴(lài)關(guān)系的處理
懶加載的 Bean 可能會(huì)被其他 Bean 所依賴(lài)。在處理依賴(lài)關(guān)系時(shí),要確保依賴(lài)的 Bean 已經(jīng)被初始化或者也進(jìn)行了懶加載。否則,可能會(huì)導(dǎo)致依賴(lài)注入失敗或出現(xiàn)異常。
延遲初始化帶來(lái)的影響
懶加載雖然可以提高應(yīng)用的啟動(dòng)性能,但也會(huì)帶來(lái)一些影響。由于 Bean 的初始化被延遲到第一次使用,因此在初始化時(shí)可能會(huì)出現(xiàn)較長(zhǎng)的延遲,對(duì)于需要立即使用的 Bean 可能會(huì)造成一定的等待時(shí)間。
內(nèi)存消耗的控制
懶加載雖然可以減少應(yīng)用啟動(dòng)時(shí)的內(nèi)存消耗,但也需要注意對(duì)內(nèi)存的控制。如果應(yīng)用中存在大量的懶加載 Bean,并且這些 Bean 在實(shí)際使用中并不頻繁,可能會(huì)導(dǎo)致過(guò)多的內(nèi)存占用。因此,需要根據(jù)應(yīng)用的具體情況,合理使用懶加載,避免過(guò)度消耗內(nèi)存。
運(yùn)行時(shí)異常的處理
由于懶加載將 Bean 的初始化延遲到運(yùn)行時(shí),因此在初始化過(guò)程中可能會(huì)發(fā)生異常。要確保適當(dāng)?shù)靥幚磉@些異常,以防止應(yīng)用的崩潰或不可預(yù)料的行為。
總結(jié)
懶加載是一種延遲加載的技術(shù),用于在需要時(shí)才加載資源,而不是在應(yīng)用啟動(dòng)時(shí)加載所有資源。在 Spring Boot 框架中,有兩種方式可以實(shí)現(xiàn)懶加載:Spring 懶加載和全局懶加載。無(wú)論是懶加載還是全局懶加載,它們都能提升應(yīng)用的性能和效率,避免不必要的資源加載。
在使用 Spring 懶加載需要注意正確的注解使用、處理依賴(lài)關(guān)系、延遲初始化帶來(lái)的影響、內(nèi)存消耗控制和異常處理等方面。合理地使用可以提高應(yīng)用性能,但也需要綜合考慮應(yīng)用的需求和場(chǎng)景,以確保有效性和穩(wěn)定性。
到此這篇關(guān)于SpringBoot項(xiàng)目速度提升之延遲初始化(Lazy Initialization)詳解的文章就介紹到這了,更多相關(guān)SpringBoot延遲初始化內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Java synchronized關(guān)鍵_動(dòng)力節(jié)點(diǎn)Java學(xué)院整理
在java中,每一個(gè)對(duì)象有且僅有一個(gè)同步鎖。這也意味著,同步鎖是依賴(lài)于對(duì)象而存在。下面通過(guò)本文給大家介紹synchronized原理 及基本規(guī)則,感興趣的朋友一起學(xué)習(xí)吧2017-05-05Android Home鍵監(jiān)聽(tīng)的實(shí)現(xiàn)代碼
這篇文章主要介紹了Android Home 鍵監(jiān)聽(tīng)的實(shí)現(xiàn)代碼,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2018-12-12如何在Maven項(xiàng)目配置pom.xml指定JDK版本和編碼
maven是個(gè)項(xiàng)目管理工具,如果我們不告訴它要使用什么樣的jdk版本編譯,它就會(huì)用maven-compiler-plugin默認(rèn)的jdk版本來(lái)處理,這樣就容易出現(xiàn)版本不匹配的問(wèn)題,這篇文章主要給大家介紹了關(guān)于如何在Maven項(xiàng)目配置pom.xml指定JDK版本和編碼的相關(guān)資料,需要的朋友可以參考下2024-01-01Jpa?Specification如何實(shí)現(xiàn)and和or同時(shí)使用查詢(xún)
這篇文章主要介紹了Jpa?Specification如何實(shí)現(xiàn)and和or同時(shí)使用查詢(xún),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-11-11SpringBoot Jpa 自定義查詢(xún)實(shí)現(xiàn)代碼詳解
這篇文章主要介紹了SpringBoot Jpa 自定義查詢(xún)實(shí)現(xiàn)代碼詳解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-02-02Springboot @WebFilter無(wú)法注入其他Bean的示例問(wèn)題
這篇文章主要介紹了Springboot @WebFilter無(wú)法注入其他Bean的示例問(wèn)題,本文通過(guò)示例代碼給大家分享解決方法,需要的朋友可以參考下2021-09-09MyBatis注解開(kāi)發(fā)之實(shí)現(xiàn)自定義映射關(guān)系和關(guān)聯(lián)查詢(xún)
本文主要詳細(xì)介紹了MyBatis注解開(kāi)發(fā)中,實(shí)現(xiàn)自定義映射關(guān)系和關(guān)聯(lián)查詢(xún),文中有詳細(xì)的代碼示例,對(duì)學(xué)習(xí)MyBatis有一定的參考價(jià)值,需要的朋友可以參考閱讀2023-04-04springboot實(shí)現(xiàn)rabbitmq的隊(duì)列初始化和綁定
這篇文章主要介紹了springboot實(shí)現(xiàn)rabbitmq的隊(duì)列初始化和綁定,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2018-10-10