詳解Spring?延遲初始化遇到的問題
List<坑> 坑列表 = new ArrayList<>(2);
首先,讓我們回顧一下 Spring 延遲初始化的概念。在 Spring 中,延遲初始化指的是將 Bean 的實(shí)例化推遲到第一次被使用時(shí),而不是在應(yīng)用程序啟動(dòng)時(shí)就立即創(chuàng)建所有的 Bean。這種延遲加載的機(jī)制可以提高應(yīng)用程序的性能和資源利用率。
坑 1. 延遲加載失效,被非延遲初始化的 Bean 注入了。
代碼演示:
@Lazy @Component public class MyBean { public MyBean() { System.out.println("My bean init success."); } }
1、 使用構(gòu)造函數(shù)注入
@Service public class MyService { private MyBean myBean; public MyService(MyBean myBean) { this.myBean = myBean; } public void exec() { System.out.println("exec suc"); } }
2、 @Resource 注入
@Service public class MyService { @Resource private MyBean myBean; public void exec() { System.out.println("exec suc"); } }
3、 @Autowired 注入
@Service public class MyService { private MyBean myBean; @Autowired public void setMyBean(MyBean myBean) { this.myBean = myBean; } public void exec() { myBean.exec(); } }
測(cè)試結(jié)果
失效原因
這個(gè)非常好理解,myService 并沒有配置@Lazy
,所以在啟動(dòng)的時(shí)候會(huì)被初始化。由于 myService 依賴 myBean,myBean 就會(huì)被注入。所以這意味著 myBean 要能正常被注入,就得被初始化,如果不初始化就會(huì)啟動(dòng)失敗。這也就是造成 myBean 延遲初始化失效的原因。
解決方法
解決方法很簡(jiǎn)單,在依賴到的地方都配置上@Lazy
,避免出現(xiàn)被非延遲初始化的 Bean 注入了。
坑 2. 延遲加載失效:Bean 的作用域錯(cuò)誤配置
@Lazy 注解只對(duì)單例(Singleton)作用域的 Bean 有效。默認(rèn)情況下,Spring 的 Bean 作用域是單例,如果將 Bean 的作用域設(shè)置為其他作用域(如原型、請(qǐng)求、會(huì)話等)的是不起作用的。
代碼演示:
- 默認(rèn)不做任何配置。
@Component public class MyBean { public MyBean() { System.out.println("My bean init success."); } public void exec() { System.out.println("exec suc"); } }
啟動(dòng)結(jié)果:
通過觀察啟動(dòng)結(jié)果,可以看到 myBean 在啟動(dòng)的時(shí)候被初始化了。
- 加上
@Lazy
@Lazy @Component public class MyBean { public MyBean() { System.out.println("My bean init success."); } public void exec() { System.out.println("exec suc"); } }
啟動(dòng)結(jié)果:
通過觀察啟動(dòng)結(jié)果,可以看到 myBean 并沒有初始化,說明@Lazy
生效了。
- 設(shè)置 scope
@Lazy @Component @Scope("prototype") public class MyBean { public MyBean() { System.out.println("My bean init success."); } public void exec() { System.out.println("exec suc"); } }
啟動(dòng)結(jié)果:
這個(gè)時(shí)候你會(huì)發(fā)現(xiàn),貌似這個(gè)結(jié)果不對(duì)呀。上面提到,@Lazy 注解只對(duì)單例(Singleton)作用域的 Bean 有效。但是我已經(jīng)將 Scope 改為 prototype。 按理來應(yīng)該是這樣:
控制臺(tái)會(huì)輸出My bean init success.
,然而事實(shí)就是沒有。那么這是為什么呢?
原因分析
由于是增加了@Scope("prototype")
,發(fā)現(xiàn)結(jié)果不符合預(yù)期,那我們就從它入手。我們先回顧一下 Spring Bean 的作用域相關(guān)的知識(shí)。當(dāng) Spring Bean 作用域?yàn)?prototype
時(shí),每次獲取 Bean 時(shí)都會(huì)重新創(chuàng)建一個(gè)實(shí)例。
換句話說,也就意味著,當(dāng)?shù)?Bean 作用域?yàn)?prototype 時(shí),Bean 在被使用的才會(huì)被初始化,并且每個(gè) Bean 都是全新的。
誒,在使用的時(shí)候被初始化,這不就是延遲初始化嗎。改下代碼測(cè)試一下:
去掉@Lazy
:
@Component @Scope("prototype") public class MyBean { public MyBean() { System.out.println("My bean init success."); } public void exec() { System.out.println("exec suc"); } }
啟動(dòng)結(jié)果:
發(fā)現(xiàn)和單獨(dú)配置@Lazy
的效果是一樣,并沒有被初始化。
結(jié)論
當(dāng) bean 作用域是 prototype 時(shí),這些 bean 每次在需要時(shí),都會(huì)按需實(shí)例化和初始化,因此它們本質(zhì)上是延遲始化的。所以給他們配置@Lazy
是沒有意義的。
在上面的案例,出現(xiàn)這樣的情況是因?yàn)椋趩?dòng)的時(shí)候 myBean 并沒有,被其他 Bean 依賴和使用。所以表現(xiàn)出和@Lazy
一樣的效果。誤以為當(dāng) Bean 作用域是 prototype 時(shí),@Lazy
可以生效。
總結(jié)
由于 spring bean 的默認(rèn)作用域是:singleton。所以在啟動(dòng)的時(shí)候 bean 會(huì)被初始化,如果被標(biāo)記了@Lazy
,會(huì)延遲初始化,但是如果被非懶加載的 Bean 注入了,@Lazy
會(huì)失效。并且@Lazy
注解只對(duì)單例 singleton 作用域的 Bean 有效。
結(jié)尾
如果覺得對(duì)你有幫助,可以多多評(píng)論,多多點(diǎn)贊哦,也可以到我的主頁(yè)看看,說不定有你喜歡的文章,也可以隨手點(diǎn)個(gè)關(guān)注哦,謝謝。
以上就是詳解Spring 延遲初始化遇到的問題的詳細(xì)內(nèi)容,更多關(guān)于Spring 延遲初始化的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
java中字符串如何計(jì)算字節(jié)長(zhǎng)度
這篇文章主要介紹了java中字符串如何計(jì)算字節(jié)長(zhǎng)度,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-10-10maven項(xiàng)目pom.xml中parent標(biāo)簽的使用小結(jié)
使用maven是為了更好的幫項(xiàng)目管理包依賴,maven的核心就是pom.xml,當(dāng)我們需要引入一個(gè)jar包時(shí),在pom文件中加上就可以從倉(cāng)庫(kù)中依賴到相應(yīng)的jar包,本文就來介紹一下maven項(xiàng)目pom.xml中parent標(biāo)簽的使用小結(jié),感興趣的可以了解一下2023-12-12RabbitMQ消息隊(duì)列實(shí)現(xiàn)延遲任務(wù)示例
這篇文章主要為大家介紹了RabbitMQ消息隊(duì)列實(shí)現(xiàn)延遲任務(wù)示例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步早日升職加薪2022-04-04Springboot+Flowable?快速實(shí)現(xiàn)工作流的開發(fā)流程
這篇文章主要介紹了Springboot+Flowable?快速實(shí)現(xiàn)工作流的開發(fā)流程,本文通過實(shí)例代碼圖文相結(jié)合給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-02-02mybatis resultmap 如何為對(duì)象賦值的調(diào)用順序
這篇文章主要介紹了mybatis resultmap 如何為對(duì)象賦值的調(diào)用順序,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-01-01