spring之Bean的循環(huán)依賴問(wèn)題-創(chuàng)新互聯(lián)

文章目錄
  • 一、Bean的循環(huán)依賴之Set注入模式下
    • 1、Husband類
    • 2、Wife類
    • 3、Spring配置文件
    • 4、測(cè)試類
    • 5、測(cè)試結(jié)果
    • 6、結(jié)論
  • 二、Bean的循環(huán)依賴之構(gòu)造方法注入模式下
    • 1、Husband類
    • 2、Wife類
    • 3、Spring配置文件
    • 4、測(cè)試類
    • 5、運(yùn)行結(jié)果
  • 三、Spring解決循環(huán)依賴的機(jī)理
    • 三級(jí)緩存(面試常問(wèn))

十余年的奇臺(tái)網(wǎng)站建設(shè)經(jīng)驗(yàn),針對(duì)設(shè)計(jì)、前端、開(kāi)發(fā)、售后、文案、推廣等六對(duì)一服務(wù),響應(yīng)快,48小時(shí)及時(shí)工作處理。營(yíng)銷型網(wǎng)站的優(yōu)勢(shì)是能夠根據(jù)用戶設(shè)備顯示端的尺寸不同,自動(dòng)調(diào)整奇臺(tái)建站的顯示方式,使網(wǎng)站能夠適用不同顯示終端,在瀏覽器中調(diào)整網(wǎng)站的寬度,無(wú)論在任何一種瀏覽器上瀏覽網(wǎng)站,都能展現(xiàn)優(yōu)雅布局與設(shè)計(jì),從而大程度地提升瀏覽體驗(yàn)。創(chuàng)新互聯(lián)公司從事“奇臺(tái)網(wǎng)站設(shè)計(jì)”,“奇臺(tái)網(wǎng)站推廣”以來(lái),每個(gè)客戶項(xiàng)目都認(rèn)真落實(shí)執(zhí)行。
一、Bean的循環(huán)依賴之Set注入模式下

A對(duì)象中有B屬性,B對(duì)象中有A屬性。這就是循環(huán)依賴。我依賴你,你也依賴我。
比如:丈夫類Husband、妻子類Wife。Husband類中有Wife類的引用。Wife類中有Husband類的引用。

1、Husband類

husband類中有wife

注意:里邊的toString方法對(duì)于wife這個(gè)屬性使用了getName()避免陷入死循環(huán)

public class Husband {private String name;
    private Wife wife;

    public void setName(String name) {this.name = name;
    }

    public void setWife(Wife wife) {this.wife = wife;
    }

    public String getName() {return name;
    }

    @Override
    public String toString() {return "Husband{" +
                "name='" + name + '\'' +
                ", wife=" + wife.getName() +
                '}';
    }
}
2、Wife類

wife類中有husband

public class Wife {private String name;
    private Husband husband;

    @Override
    public String toString() {return "Wife{" +
                "name='" + name + '\'' +
                ", husband=" + husband.getName() +
                '}';
    }

    public String getName() {return name;
    }

    public void setName(String name) {this.name = name;
    }

    public void setHusband(Husband husband) {this.husband = husband;
    }
}
3、Spring配置文件

配置兩個(gè)bean

4、測(cè)試類
@Test
    public void testDeprndency(){ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring2.xml");
        Husband husband = applicationContext.getBean("husband", Husband.class);
        System.out.println(husband);

        Wife wife = applicationContext.getBean("wife", Wife.class);
        System.out.println(wife);
    }
5、測(cè)試結(jié)果

在這里插入圖片描述

6、結(jié)論

singleotn + setter模式下的循環(huán)依賴 spring是沒(méi)有任何問(wèn)題的。
singleotn 表示在整個(gè)Spring容器當(dāng)中是單例的,獨(dú)一無(wú)二的。

singleotn + setter模式下的循環(huán)依賴 spring是如何應(yīng)對(duì)的?

主要原因是在這種模式下,Spring對(duì)Bean的管理主要分為清晰的兩個(gè)階段:
第一個(gè)階段:在Spring容器加載的時(shí)候,實(shí)例化Bean,只要其中任意一個(gè)Bean實(shí)例化之后,馬上進(jìn)行“曝光”【不等屬性賦值就曝光】
第二個(gè)階段:Bean“曝光”之后,再進(jìn)行屬性的賦值。
核心解決方案是:實(shí)例化對(duì)象和對(duì)象的屬性賦值分為兩個(gè)階段來(lái)完成的。
只有在scope是singleton的情況下,Bean才會(huì)采取提前“曝光”的措施

prototy+ setter模式下的循環(huán)依賴 spring是會(huì)出現(xiàn)異常的

在這里插入圖片描述
Bean的循環(huán)依賴出現(xiàn)問(wèn)題:BeanCurrentlyInCreationException
注意:當(dāng)兩個(gè)Bean的scope都是prototype的時(shí)候,才會(huì)出現(xiàn)異常,如果其中任意一個(gè)是singleton,就不會(huì)出現(xiàn)異常

二、Bean的循環(huán)依賴之構(gòu)造方法注入模式下 1、Husband類

去掉set方法,加入構(gòu)造方法

public class Husband {private String name;
    private Wife wife;

    public Husband(String name, Wife wife) {this.name = name;
        this.wife = wife;
    }
    public String getName() {return name;
    }
    @Override
    public String toString() {return "Husband{" +
                "name='" + name + '\'' +
                ", wife=" + wife.getName() +
                '}';
    }
}
2、Wife類

去掉set方法,加入構(gòu)造方法

public class Wife {private String name;
    private Husband husband;

    public Wife(String name, Husband husband) {this.name = name;
        this.husband = husband;
    }

    @Override
    public String toString() {return "Wife{" +
                "name='" + name + '\'' +
                ", husband=" + husband.getName() +
                '}';
    }

    public String getName() {return name;
    }
}
3、Spring配置文件

構(gòu)造注入,這種循環(huán)依賴是否會(huì)出現(xiàn)問(wèn)題?

4、測(cè)試類
@Test
    public void testDeprndency(){ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring2.xml");
        Husband husband = applicationContext.getBean("husband", Husband.class);
        System.out.println(husband);

        Wife wife = applicationContext.getBean("wife", Wife.class);
        System.out.println(wife);
    }
5、運(yùn)行結(jié)果

在這里插入圖片描述
注意:基于構(gòu)造注入的方式下產(chǎn)生的循環(huán)依賴也是無(wú)法解決的

Spring只能解決set+singleton模式下的循環(huán)依賴。

三、Spring解決循環(huán)依賴的機(jī)理

根本原因在于:這種方式可以做到將“實(shí)例化Bean”和“給Bean屬性賦值”這兩個(gè)動(dòng)作分開(kāi)去完成。

  • 實(shí)例化Bean的時(shí)候:調(diào)用無(wú)參數(shù)構(gòu)造方法來(lái)完成,此時(shí)可以先不給屬性賦值,可以提前將該Bean對(duì)象“曝光”給外界。
  • 給Bean對(duì)象屬性賦值的時(shí)候:調(diào)用setter方法來(lái)完成。

兩個(gè)步驟完全是可以分離開(kāi)去完成的,并且不要求在同一時(shí)間點(diǎn)上完成。

也就是說(shuō)Bean都是單例的,我們可以先把所有的單例Bean實(shí)例化出來(lái),放到一個(gè)集合當(dāng)中(緩存),所有的單例Bean全部實(shí)例化之后。我們?cè)俾恼{(diào)用setter方法給屬性賦值,這樣就解決了循環(huán)依賴的問(wèn)題。

追源碼:
雙擊shift: AbstractAutowireCapableBeanFactory
ctrl + f :doCreateBean 方法

debug:
在這里插入圖片描述
繼續(xù)往下走一步:
這個(gè)husband對(duì)象的name屬性和wife屬性是空的,但是這個(gè)對(duì)象已經(jīng)創(chuàng)建出來(lái)了
在這里插入圖片描述
走到下一個(gè)斷點(diǎn):
在這里插入圖片描述
把這個(gè)單例對(duì)象緩存起來(lái),具體看看怎么緩存的:

三級(jí)緩存(面試常問(wèn))

step into進(jìn)去一個(gè)新的類:DefaultSingletonBeanRegistry

在這里插入圖片描述

先說(shuō)說(shuō)這個(gè)類DefaultSingletonBeanRegistry中的三個(gè)比較重要的緩存:
private final MapsingletonObjects ------ 一級(jí)緩存
private final MapearlySingletonObjects ------ 二級(jí)緩存
private final Map>singletonFactories ------ 三級(jí)緩存

這三個(gè)緩存都是Map集合。Map集合的key存儲(chǔ)的都是bean的name(bean id)。

一級(jí)緩存存儲(chǔ)的是:完整的單例Bean對(duì)象。也就是說(shuō)這個(gè)緩存中的Bean對(duì)象的屬性都已經(jīng)賦值了。是一個(gè)完整的Bean對(duì)象

二級(jí)緩存存儲(chǔ)的是:早期的單例Bean對(duì)象。這個(gè)緩存中的單例Bean對(duì)象的屬性沒(méi)有賦值,只是一個(gè)早期的實(shí)例對(duì)象

三級(jí)緩存存儲(chǔ)的是:?jiǎn)卫S對(duì)象。這個(gè)里面存儲(chǔ)了大量的“工廠對(duì)象”,每一個(gè)單例Bean對(duì)象都會(huì)對(duì)應(yīng)一個(gè)單例工廠對(duì)象。這個(gè)集合中存儲(chǔ)的是:創(chuàng)建該單例對(duì)象時(shí)對(duì)應(yīng)的那個(gè)單例工廠對(duì)象

繼續(xù)回到debug:
進(jìn)來(lái)DefaultSingletonBeanRegistry這個(gè)類之后addSingletonFactory這個(gè)方法執(zhí)行
在這里插入圖片描述
繼續(xù)執(zhí)行到:
并沒(méi)有把Bean對(duì)象存進(jìn)去,是把創(chuàng)建Bean對(duì)象的工廠對(duì)象存放到map集合。(三級(jí)緩存)
往map對(duì)象存的這個(gè)動(dòng)作就叫做“曝光”
在這里插入圖片描述
“曝光”工廠之后會(huì)繼續(xù)調(diào)用getSingleton方法
在這里插入圖片描述
然后從一級(jí)緩存取對(duì)象,拿不到從二級(jí)緩存取,拿不到從三級(jí)緩存取,
三級(jí)緩存取工廠對(duì)象,獲取這個(gè)Bean對(duì)象,再把Bean對(duì)象放到二級(jí)緩存。
在這里插入圖片描述
最后執(zhí)行
populateBean(beanName, mbd, instanceWrapper);才會(huì)給屬性賦值


你是否還在尋找穩(wěn)定的海外服務(wù)器提供商?創(chuàng)新互聯(lián)www.cdcxhl.cn海外機(jī)房具備T級(jí)流量清洗系統(tǒng)配攻擊溯源,準(zhǔn)確流量調(diào)度確保服務(wù)器高可用性,企業(yè)級(jí)服務(wù)器適合批量采購(gòu),新人活動(dòng)首月15元起,快前往官網(wǎng)查看詳情吧

當(dāng)前標(biāo)題:spring之Bean的循環(huán)依賴問(wèn)題-創(chuàng)新互聯(lián)
本文路徑:http://muchs.cn/article8/dsijop.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供Google、服務(wù)器托管建站公司、關(guān)鍵詞優(yōu)化、微信公眾號(hào)、外貿(mào)建站

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)

外貿(mào)網(wǎng)站制作