最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Spring解決循環(huán)依賴問題及三級緩存的作用

 更新時間:2022年07月08日 17:01:47   作者:向著百萬年薪努力的小趙  
這篇文章主要介紹了Spring解決循環(huán)依賴問題及三級緩存的作用,所謂的三級緩存只是三個可以當(dāng)作是全局變量的Map,Spring的源碼中大量使用了這種先將數(shù)據(jù)放入容器中等使用結(jié)束再銷毀的代碼風(fēng)格

前言

所謂的三級緩存只是三個可以當(dāng)作是全局變量的Map,Spring的源碼中大量使用了這種先將數(shù)據(jù)放入容器中等使用結(jié)束再銷毀的代碼風(fēng)格

Spring的初始化過程大致有四步:

  • 創(chuàng)建beanFactory,加載配置文件
  • 解析配置文件轉(zhuǎn)化beanDefination,獲取到bean的所有屬性、依賴及初始化用到的各類處理器等
  • 刷新beanFactory容器,初始化所有單例bean
  • 注冊所有的單例bean并返回可用的容器

我們說的循環(huán)依賴就是第四步在給Bean屬性注入的時候發(fā)生的一個問題

1什么是循環(huán)依賴

循環(huán)依賴就是:

假設(shè)有兩個類 A和B,A中需要注入B,B中需要注入A
由于A注入B時B沒有創(chuàng)建,B創(chuàng)建時A也無法創(chuàng)建導(dǎo)致的死循環(huán)問題

2 如何解決循環(huán)依賴

我們都知道AOP是Spring的一個重要核心思想,其實現(xiàn)就是根據(jù)動態(tài)代理來實現(xiàn)的,也就是說我們的Bean其實很大概率都是要生成代理類,讓我們先來看無代理的情況:

Bean的初始化大概是這樣的:

根據(jù)以上步驟可以看出bean初始化是一個相當(dāng)復(fù)雜的過程,假如初始化A bean時,發(fā)現(xiàn)A bean依賴B bean,即A初始化執(zhí)行到了第4步填充屬性,需要注入B bean,此時B還沒有初始化,則需要暫停A,先去初始化B,那么此時new出來的A對象放哪里,直接放在容器Map里顯然不合適,半殘品怎么能用,所以需要提供一個可以標(biāo)記創(chuàng)建中bean(A)的Map,可以提前暴露正在創(chuàng)建的bean供其他bean依賴,而如果初始化A所依賴的bean B時,發(fā)現(xiàn)B也需要注入一個A的依賴(即發(fā)生循環(huán)依賴),則B可以從創(chuàng)建中的beanMap中直接獲取A對象(創(chuàng)建中)注入A,然后完成B的初始化,返回給正在注入屬性的A,最終A也完成初始化,皆大歡喜。

如果沒有循環(huán)依賴,A 依賴B,就是創(chuàng)建B,B依賴C就去創(chuàng)建C,創(chuàng)建完了逐級返回就行,并不需要什么緩存,所以,一級緩存之后的其他緩存(二三級緩存)就是為了解決循環(huán)依賴而設(shè)立的
一級緩存其實就是我們的成熟的Bean了,可以直接被使用

我們?nèi)タ匆幌略创a:

從源碼中我們可以看到,三級緩存里放的并不是實例化的Bean,而是一個工廠,這是為什么呢?
循環(huán)依賴在實際應(yīng)用可能會有,但很少,簡單的應(yīng)用場景是: controller注入service,service注入mapper,只有復(fù)雜的業(yè)務(wù),可能service互相引用,有可能出現(xiàn)循環(huán)依賴,所以為了出現(xiàn)循環(huán)依賴才去解決,不出現(xiàn)就不解決,雖然支持循環(huán)依賴,但是只有在出現(xiàn)循環(huán)依賴時才真正暴露早期對象,否則只暴露個獲取bean的方法,并沒有真正暴露bean,因為這個方法不會被執(zhí)行到,這塊的實現(xiàn)就是三級緩存(singletonFactories),只緩存了一個單例bean工廠
為什么是一個工廠?或者說這個工廠的作用?
三級緩存bean工廠的getObject方式,實際執(zhí)行的是getEarlyBeanReference,如果對象需要被代理(存在beanPostProcessors -> SmartInstantiationAwareBeanPostProcessor),則提前生成代理對象。

三級緩存已經(jīng)解決所有問題了,二級緩存用來做什么呢?為什么三級緩存不直接叫做二級緩存?這個應(yīng)該是在緩存使用時決定的:

此時這個方法中的判斷邏輯是:

  • 一級緩存中沒有
  • 對象A確實正在創(chuàng)建中
  • 二級緩存中也沒有
  • 最終去三級緩存中獲取對象,從三級緩存獲取后把對象從三級緩存刪除然后放入到二級緩存中,由于當(dāng)初放入到三級緩存中的是一個工廠,所以從三級緩存中拿對象是調(diào)用getEarlyBeanReference這個方法獲取,這個方法的作用是如果對象需要代理,那么就返回代理類,如果不需要代理就返回原生類,至此屬性注入A完成

那么為什么要把對象從三級緩存放到二級緩存呢?

給大家一個循環(huán)依賴的流程圖,大家一看便知:

看到了嗎,如果AB都需要代理,我們在A的屬性注入時創(chuàng)建了B,但是此時A還是原生的A,但是我們需要代理A,而代理A在B注入A時已經(jīng)創(chuàng)建并放入二級緩存中了,我們直接從二級緩存拿然后替換原生A即可。

所以,我理解的是二級緩存是為了應(yīng)對代理這個情況而生的
至此,循環(huán)依賴的問題已經(jīng)完美解決

3無法解決的循環(huán)依賴

構(gòu)造函數(shù)循環(huán)依賴:

如果我們的成員屬性是在構(gòu)造函數(shù)里呢?
首先要解決循環(huán)依賴就是要先實例化,然后放入三級緩存暴露出來,那么如果是構(gòu)造函數(shù)這一步循環(huán)依賴,
實例化的時候就會產(chǎn)生無限遞歸創(chuàng)建,所以不能解決

多例的循環(huán)依賴:

如果是多例的,在容器初始化的時候,不會去創(chuàng)建,所以早期沒有放入到三級緩存中暴露出來,所以無法解決循環(huán)依賴,會報錯

到此這篇關(guān)于Spring解決循環(huán)依賴問題及三級緩存的作用的文章就介紹到這了,更多相關(guān)Spring解決循環(huán)依賴問題內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • springboot使用Thymeleaf報錯常見的幾種解決方案

    springboot使用Thymeleaf報錯常見的幾種解決方案

    這篇文章主要介紹了springboot使用Thymeleaf報錯常見的幾種解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-11-11
  • java實現(xiàn)文件的上傳功能

    java實現(xiàn)文件的上傳功能

    這篇文章主要為大家詳細(xì)介紹了java實現(xiàn)文件的上傳功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-01-01
  • Java web實現(xiàn)賬號單一登錄,防止同一賬號重復(fù)登錄(踢人效果)

    Java web實現(xiàn)賬號單一登錄,防止同一賬號重復(fù)登錄(踢人效果)

    這篇文章主要介紹了Java web實現(xiàn)賬號單一登錄,防止同一賬號重復(fù)登錄,有點類似于qq登錄踢人效果,本文給大家介紹的非常詳細(xì),具有一定的參考借鑒價值,需要的朋友可以參考下
    2019-10-10
  • Java簡明解讀代碼塊的應(yīng)用

    Java簡明解讀代碼塊的應(yīng)用

    所謂代碼塊是指用"{}"括起來的一段代碼,根據(jù)其位置和聲明的不同,可以分為普通代碼塊、構(gòu)造塊、靜態(tài)塊、和同步代碼塊。如果在代碼塊前加上 synchronized關(guān)鍵字,則此代碼塊就成為同步代碼塊
    2022-07-07
  • Java實現(xiàn)批量導(dǎo)入excel表格數(shù)據(jù)到數(shù)據(jù)庫中的方法

    Java實現(xiàn)批量導(dǎo)入excel表格數(shù)據(jù)到數(shù)據(jù)庫中的方法

    這篇文章主要介紹了Java實現(xiàn)批量導(dǎo)入excel表格數(shù)據(jù)到數(shù)據(jù)庫中的方法,結(jié)合實例形式詳細(xì)分析了java導(dǎo)入Excel數(shù)據(jù)到數(shù)據(jù)庫的具體步驟與相關(guān)操作技巧,需要的朋友可以參考下
    2017-10-10
  • Spring Boot框架中的@Conditional注解示例詳解

    Spring Boot框架中的@Conditional注解示例詳解

    這篇文章主要介紹了Spring Boot框架中的@Conditional系列注解,@ConditionalOnProperty注解的作用是解析application.yml/application.properties 里的配置生成條件來生效,也是與@Configuration注解一起使用,本文通過示例代碼給大家介紹的非常詳細(xì),需要的朋友一起看看吧
    2022-09-09
  • Spring中的@ConditionalOnProperty作用和用法詳解

    Spring中的@ConditionalOnProperty作用和用法詳解

    這篇文章主要介紹了Spring中的@ConditionalOnProperty作用和用法詳解,在spring boot中有時候需要控制配置類是否生效,可以使用@ConditionalOnProperty注解來控制@Configuration是否生效,需要的朋友可以參考下
    2023-11-11
  • Java接口的作用以及使用說明

    Java接口的作用以及使用說明

    接口是一種規(guī)范,定義了一組方法的原型,但沒有實現(xiàn),類通過實現(xiàn)接口來實現(xiàn)接口中的抽象方法,接口可以提供規(guī)范性、擴展性和可插入性,在Java中,接口可以用來聲明一個變量,實現(xiàn)接口的類必須實現(xiàn)接口中定義的所有方法,接口提供了一種機制
    2024-11-11
  • Mybatis Plus 代碼生成器的實現(xiàn)

    Mybatis Plus 代碼生成器的實現(xiàn)

    這篇文章主要介紹了Mybatis Plus 代碼生成器的實現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-09-09
  • Java日常練習(xí)題,每天進步一點點(8)

    Java日常練習(xí)題,每天進步一點點(8)

    下面小編就為大家?guī)硪黄狫ava基礎(chǔ)的幾道練習(xí)題(分享)。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧,希望可以幫到你
    2021-07-07

最新評論

阜城县| 监利县| 顺义区| 淳安县| 犍为县| 清新县| 榕江县| 平凉市| 隆化县| 稷山县| 赤峰市| 扶余县| 泗水县| 金溪县| 濮阳县| 枞阳县| 云霄县| 沭阳县| 依兰县| 曲阳县| 克拉玛依市| 河北区| 郴州市| 安福县| 凌源市| 循化| 巫溪县| 高要市| 偃师市| 临江市| 当雄县| 荆州市| 山阳县| 双峰县| 怀来县| 吉安市| 江川县| 塔河县| 绥江县| 黔东| 社旗县|