欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Spring解決循環(huán)依賴(lài)問(wèn)題及三級(jí)緩存的作用

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

前言

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

Spring的初始化過(guò)程大致有四步:

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

我們說(shuō)的循環(huán)依賴(lài)就是第四步在給Bean屬性注入的時(shí)候發(fā)生的一個(gè)問(wèn)題

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

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

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

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

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

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

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

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

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

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

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

此時(shí)這個(gè)方法中的判斷邏輯是:

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

那么為什么要把對(duì)象從三級(jí)緩存放到二級(jí)緩存呢?

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

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

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

3無(wú)法解決的循環(huán)依賴(lài)

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

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

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

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

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

相關(guān)文章

  • Spring MVC整合Kaptcha的具體使用

    Spring MVC整合Kaptcha的具體使用

    Kaptcha 是一個(gè)可高度配置的實(shí)用驗(yàn)證碼生成工具,本文主要介紹了Spring MVC整合Kaptcha的具體使用,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2022-06-06
  • SpringBoot集成SFTP客戶(hù)端實(shí)現(xiàn)文件上傳下載實(shí)例

    SpringBoot集成SFTP客戶(hù)端實(shí)現(xiàn)文件上傳下載實(shí)例

    這篇文章主要為大家介紹了SpringBoot集成SFTP客戶(hù)端實(shí)現(xiàn)文件上傳下載實(shí)例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-08-08
  • 詳解Java的初始化與清理

    詳解Java的初始化與清理

    這篇文章主要介紹了Java的初始化與清理,文中示例代碼非常詳細(xì),幫助大家更好的理解和學(xué)習(xí),感興趣的朋友可以了解下
    2020-07-07
  • Java判斷object對(duì)象為空(包括null ,““)的方法

    Java判斷object對(duì)象為空(包括null ,““)的方法

    這篇文章主要介紹了Java判斷對(duì)象是否為空(包括null ,“”)的方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2023-12-12
  • Jdbc連接數(shù)據(jù)庫(kù)基本步驟詳解

    Jdbc連接數(shù)據(jù)庫(kù)基本步驟詳解

    這篇文章主要為大家詳細(xì)介紹了Jdbc連接數(shù)據(jù)庫(kù)的基本步驟,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-10-10
  • idea中自動(dòng)生成Java類(lèi)圖和時(shí)序圖的圖文教程

    idea中自動(dòng)生成Java類(lèi)圖和時(shí)序圖的圖文教程

    本文主要介紹了idea中自動(dòng)生成Java類(lèi)圖和時(shí)序圖的圖文教程,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2023-07-07
  • Spring?Boot中調(diào)用外部接口的3種方式步驟

    Spring?Boot中調(diào)用外部接口的3種方式步驟

    這篇文章主要給大家介紹了關(guān)于Spring?Boot中調(diào)用外部接口的3種方式步驟,在Spring-Boot項(xiàng)目開(kāi)發(fā)中,存在著本模塊的代碼需要訪問(wèn)外面模塊接口,或外部url鏈接的需求,需要的朋友可以參考下
    2023-08-08
  • springboot使用yml文件配置多環(huán)境方式(dev、test、prod)

    springboot使用yml文件配置多環(huán)境方式(dev、test、prod)

    這篇文章主要介紹了springboot使用yml文件配置多環(huán)境方式(dev、test、prod),具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-09-09
  • SpringMVC日期類(lèi)型參數(shù)傳遞實(shí)現(xiàn)步驟講解

    SpringMVC日期類(lèi)型參數(shù)傳遞實(shí)現(xiàn)步驟講解

    這篇文章主要介紹了SpringMVC日期類(lèi)型參數(shù)傳遞實(shí)現(xiàn)步驟,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)吧
    2023-02-02
  • SpringBoot里使用Servlet進(jìn)行請(qǐng)求的實(shí)現(xiàn)示例

    SpringBoot里使用Servlet進(jìn)行請(qǐng)求的實(shí)現(xiàn)示例

    這篇文章主要介紹了SpringBoot里使用Servlet進(jìn)行請(qǐng)求的實(shí)現(xiàn)示例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2021-01-01

最新評(píng)論