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

Spring如何使用三級(jí)緩存解決循環(huán)依賴

 更新時(shí)間:2024年11月08日 08:49:53   作者:夏詩曼CharmaineXia  
在Spring框架中,循環(huán)依賴是指兩個(gè)或多個(gè)Bean相互依賴,形成閉環(huán),導(dǎo)致無法完成初始化,此問題僅存在于單例Bean中,而原型Bean會(huì)拋出異常,Spring通過三級(jí)緩存及提前暴露策略解決循環(huán)依賴:一級(jí)緩存存放完全初始化的Bean

前言

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

類A需要類B,我們就叫做類A依賴類B。簡單說就是依賴,或者和別的類相互依賴

1.1 互相依賴

1.2 遞歸依賴

2. Sping中循環(huán)依賴有什么問題?

在Spring中,循環(huán)依賴指的是兩個(gè)或多個(gè)Bean之間相互依賴形成的循環(huán)引用關(guān)系。具體來說,當(dāng)Bean A依賴于Bean B,而Bean B又依賴于Bean A時(shí),就形成了循環(huán)依賴。

只有單例的 Bean 才存在循環(huán)依賴的情況,原型(Prototype)情況下,Spring 會(huì)直接拋出異常。

循環(huán)依賴可能導(dǎo)致以下問題:

  • 無法完成Bean的初始化:當(dāng)存在循環(huán)依賴時(shí),Spring容器無法確定先初始化哪個(gè)Bean,因?yàn)樗鼈兿嗷ヒ蕾嚕叶夹枰獙?duì)方完成初始化才能繼續(xù)。這可能導(dǎo)致Bean的初始化過程無法完成,從而引發(fā)異常。
  • 無限遞歸調(diào)用:當(dāng)存在循環(huán)依賴時(shí),Spring容器可能會(huì)陷入無限遞歸的調(diào)用中,導(dǎo)致系統(tǒng)堆棧溢出。這是因?yàn)槊看潍@取Bean時(shí),Spring容器需要檢測循環(huán)依賴并創(chuàng)建實(shí)例,但由于循環(huán)依賴的存在,無法正常創(chuàng)建實(shí)例,從而導(dǎo)致無限遞歸調(diào)用。

為了解決循環(huán)依賴問題,Spring使用了三級(jí)緩存和"提前暴露"的策略

3. 什么是三級(jí)緩存

對(duì)于創(chuàng)建單例Bean,Spring創(chuàng)建了三個(gè)容器來存儲(chǔ)不同時(shí)期的對(duì)象:

  1. ?級(jí)緩存 : Map<String,Object> singletonObjects,單例池,?于保存實(shí)例化、屬性賦值(注?)、初始化完成的 bean 實(shí)例
  2. ?級(jí)緩存 : Map<String,Object> earlySingletonObjects,早期曝光對(duì)象,?于保存實(shí)例化完成的 bean 實(shí)例
  3. 三級(jí)緩存 : Map<String,ObjectFactory<?>> singletonFactories,早期曝光對(duì)象??,?于保存 bean 創(chuàng)建??,以便于后?擴(kuò)展有機(jī)會(huì)創(chuàng)建代理對(duì)象

4. Spring 可以解決哪些情況的循環(huán)依賴?

Spring 不?持基于構(gòu)造器注?的循環(huán)依賴,假如 AB 循環(huán)依賴,其中一方使用構(gòu)造器注入,也是不支持的。

為什么呢?下面二級(jí)緩存會(huì)說明白。

二級(jí)緩存作用——普通循環(huán)依賴

只用一級(jí)緩存和二級(jí)緩存就能解決普通bean的循環(huán)依賴。

先回顧Bean對(duì)象創(chuàng)建的步驟:

二級(jí)緩存:又稱 半成品池 存放的是實(shí)例化,但未屬性賦值和初始化的Bean對(duì)象。一級(jí)緩存:又稱 單例池 存放的是完成屬性賦值和初始化的成品Bean,可以直接使用了。

那么二級(jí)緩存是如何解決普通Bean的循環(huán)依賴的?

實(shí)操環(huán)節(jié)

類A依賴類B,類B依賴類A。

1. 實(shí)例化類A對(duì)象

對(duì)象a被實(shí)例化出來,會(huì)被放到半成品池中,當(dāng)進(jìn)行下一步屬性賦值時(shí),發(fā)現(xiàn)依賴了類B,所以開始創(chuàng)建對(duì)象b。

如果對(duì)象b是在a的構(gòu)造函數(shù)中注入的,那就完了,a無法實(shí)例化,得先去實(shí)例化b,若是b也是構(gòu)造函數(shù)中注入的a,那就無解了。

public class A {
    private B b;

    @Inject
    public A(B b) {
        this.b = b;
    }
}

2. 實(shí)例化類B對(duì)象

對(duì)象b被實(shí)例化出來,也被放到半成品池中。下一步是屬性賦值,發(fā)現(xiàn)依賴了類A,會(huì)依次從?級(jí)到三級(jí)緩存查詢類A對(duì)象,最終會(huì)在半成品池中找到對(duì)象a,成功將它賦值到自己的屬性中。

3. B對(duì)象完成創(chuàng)建

對(duì)象b在經(jīng)過填充屬性、初始化后會(huì)從半成品池里挪到單例池中,可以直接使用了。

4.繼續(xù)創(chuàng)建A對(duì)象

這時(shí)候回過頭來繼續(xù)對(duì)象a的屬性注入,把對(duì)象b賦值給自己的屬性后再經(jīng)過初始化,對(duì)象a也從半成品池挪到單例池,對(duì)象a創(chuàng)建完成,對(duì)象b也跟著創(chuàng)建完成。

三級(jí)緩存作用——aop循環(huán)依賴

二級(jí)緩存仍然存在問題,它無法解決AOP代理問題。

1. AOP代理問題

AOP(面向切面)簡單的說,在不改源碼的情況下在原始方法前后加一些代碼。

它的底層是靠動(dòng)態(tài)代理實(shí)現(xiàn)的,即生成一個(gè)代理類,重新原始方法,真正使用的時(shí)候其實(shí)用的是代理類對(duì)象,而非原始類對(duì)象。

既然用的是代理類對(duì)象,單例池中應(yīng)該存放的就該是代理類對(duì)象。

二級(jí)緩存無法解決生成代理對(duì)象的問題,因?yàn)閯?chuàng)建對(duì)象的過程很復(fù)雜,每個(gè)代理類都需要一個(gè)工廠來專門生成代理類對(duì)象。

三級(jí)緩存又叫工廠池,就是用來存放生成代理類對(duì)象工廠的。

2. 何時(shí)生成代理對(duì)象

AOP是靠AOP處理器實(shí)現(xiàn)的,處理器有兩個(gè)生成代理對(duì)象的方式。

前置處理:在Bean對(duì)象初始化后后置處理:再Bean對(duì)象實(shí)例化前

Spring為了解決使用AOP的對(duì)象循環(huán)依賴的問題,使用了這兩種處理方式。

實(shí)操環(huán)節(jié)

類A依賴類B,類B依賴類A,類A使用了AOP。

1.實(shí)例化類A對(duì)象

首先把創(chuàng)建類A代理對(duì)象的工廠對(duì)象放到工廠池中。

類A實(shí)例化對(duì)象時(shí)發(fā)現(xiàn)依賴了類B,使用前置處理器生成A的代理對(duì)象,放在半成品池子中。

2. 實(shí)例化類B對(duì)象

對(duì)象b找到對(duì)象a,成功屬性賦值,再經(jīng)過初始化成功創(chuàng)建,挪到單例池中待用。

如果類B也使用了AOP,那么對(duì)象b在初始化后,會(huì)通過后置處理器生成動(dòng)態(tài)代理對(duì)象,放到單例池中。

3.繼續(xù)創(chuàng)建A對(duì)象

對(duì)象b創(chuàng)建完,接著回頭創(chuàng)建對(duì)象a,這個(gè)過程就很順利了。

當(dāng)對(duì)象a完成初始化以后,因?yàn)橐呀?jīng)是代理對(duì)象,就不會(huì)在走后置處理。

對(duì)象a、b都創(chuàng)建完,會(huì)清空在二級(jí)、三級(jí)池中的相關(guān)數(shù)據(jù),最終只在單例池中保留一份對(duì)象。

總結(jié)

盡管Spring提供了解決循環(huán)依賴的機(jī)制,但循環(huán)依賴本身是一個(gè)設(shè)計(jì)上的問題,可能導(dǎo)致代碼的可讀性和可維護(hù)性下降。因此,在編寫代碼時(shí),應(yīng)盡量避免出現(xiàn)循環(huán)依賴的情況。

以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • java maven項(xiàng)目如何讀取配置文件信息

    java maven項(xiàng)目如何讀取配置文件信息

    這篇文章主要介紹了java maven項(xiàng)目如何讀取配置文件信息,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-11-11
  • 解決Maven項(xiàng)目pom.xml文件Ignored的問題

    解決Maven項(xiàng)目pom.xml文件Ignored的問題

    在Maven項(xiàng)目中,若不慎刪除了.iml文件,可能會(huì)導(dǎo)致pom.xml文件顯示為Ignored狀態(tài),影響項(xiàng)目構(gòu)建,解決方法是通過IDEA的設(shè)置取消Ignored Files中對(duì)應(yīng)文件的忽略,再刷新Maven項(xiàng)目即可恢復(fù),此操作可有效解決pom.xml文件被誤忽略的問題,保證項(xiàng)目正常構(gòu)建和運(yùn)行
    2024-09-09
  • 淺談java異常鏈與異常丟失

    淺談java異常鏈與異常丟失

    下面小編就為大家?guī)硪黄獪\談java異常鏈與異常丟失。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2016-09-09
  • 深入解析Java的包(package)

    深入解析Java的包(package)

    這篇文章主要介紹了深入解析Java的包(package),是Java入門學(xué)習(xí)中的基礎(chǔ)知識(shí),需要的朋友可以參考下
    2015-09-09
  • javaWeb連接數(shù)據(jù)庫實(shí)現(xiàn)簡單登陸注冊(cè)功能的全過程

    javaWeb連接數(shù)據(jù)庫實(shí)現(xiàn)簡單登陸注冊(cè)功能的全過程

    初學(xué)javaWeb,老師留下一小作業(yè),用JAVA實(shí)現(xiàn)與服務(wù)器端交互,實(shí)現(xiàn)登錄和注冊(cè)功能,下面這篇文章主要給大家介紹了關(guān)于javaWeb連接數(shù)據(jù)庫實(shí)現(xiàn)簡單登陸注冊(cè)功能的相關(guān)資料,需要的朋友可以參考下
    2022-06-06
  • Java 由淺入深帶你掌握?qǐng)D的遍歷

    Java 由淺入深帶你掌握?qǐng)D的遍歷

    圖的遍歷是指,從給定圖中任意指定的頂點(diǎn)(稱為初始點(diǎn))出發(fā),按照某種搜索方法沿著圖的邊訪問圖中的所有頂點(diǎn),使每個(gè)頂點(diǎn)僅被訪問一次,這個(gè)過程稱為圖的遍歷。遍歷過程中得到的頂點(diǎn)序列稱為圖遍歷序列
    2022-03-03
  • 使用SpringCache進(jìn)行緩存數(shù)據(jù)庫查詢方式

    使用SpringCache進(jìn)行緩存數(shù)據(jù)庫查詢方式

    這篇文章主要介紹了使用SpringCache進(jìn)行緩存數(shù)據(jù)庫查詢方式,具有很好的參考價(jià)值,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-10-10
  • Maven中<distributionManagement>的使用及說明

    Maven中<distributionManagement>的使用及說明

    本文主要介紹了Maven中的SNAPSHOT和RELEASE倉庫的區(qū)別,以及如何在POM文件中配置和使用快照版本,快照版本可以實(shí)現(xiàn)實(shí)時(shí)更新,方便開發(fā)過程中的依賴管理,同時(shí),本文還總結(jié)了Maven的一些常用命令及其作用
    2025-01-01
  • Java?Mybatis框架由淺入深全解析上篇

    Java?Mybatis框架由淺入深全解析上篇

    MyBatis是一個(gè)優(yōu)秀的持久層框架,它對(duì)jdbc的操作數(shù)據(jù)庫的過程進(jìn)行封裝,使開發(fā)者只需要關(guān)注SQL本身,而不需要花費(fèi)精力去處理例如注冊(cè)驅(qū)動(dòng)、創(chuàng)建connection、創(chuàng)建statement、手動(dòng)設(shè)置參數(shù)、結(jié)果集檢索等jdbc繁雜的過程代碼本文將為大家初步的介紹一下MyBatis的使用
    2022-07-07
  • Java 比較字符串實(shí)例詳解

    Java 比較字符串實(shí)例詳解

    這篇文章主要介紹了 Java 比較字符串實(shí)例詳解的相關(guān)資料,需要的朋友可以參考下
    2017-06-06

最新評(píng)論