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

Bean的循環(huán)依賴問題全面解析

 更新時間:2025年12月16日 09:23:59   作者:SadSunset  
文章介紹了Spring框架如何解決setter方法注入的單例bean之間的循環(huán)依賴問題,本文結(jié)合實(shí)例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友參考下吧

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

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

package com.powernode.spring6.bean;
/**
 * @author 動力節(jié)點(diǎn)
 * @version 1.0
 * @className Husband
 * @since 1.0
 **/
public class Husband {
    private String name;
    private Wife wife;
}
package com.powernode.spring6.bean;
/**
 * @author 動力節(jié)點(diǎn)
 * @version 1.0
 * @className Wife
 * @since 1.0
 **/
public class Wife {
    private String name;
    private Husband husband;
}

singleton下的set注入產(chǎn)生的循環(huán)依賴

我們來編寫程序,測試一下在singleton+setter的模式下產(chǎn)生的循環(huán)依賴,Spring是否能夠解決?

package com.powernode.spring6.bean;
/**
 * @author 動力節(jié)點(diǎn)
 * @version 1.0
 * @className Husband
 * @since 1.0
 **/
public class Husband {
    private String name;
    private Wife wife;
    public void setName(String name) {
        this.name = name;
    }
    public String getName() {
        return name;
    }
    public void setWife(Wife wife) {
        this.wife = wife;
    }
    // toString()方法重寫時需要注意:不能直接輸出wife,輸出wife.getName()。要不然會出現(xiàn)遞歸導(dǎo)致的棧內(nèi)存溢出錯誤。
    @Override
    public String toString() {
        return "Husband{" +
                "name='" + name + '\'' +
                ", wife=" + wife.getName() +
                '}';
    }
}
package com.powernode.spring6.bean;
/**
 * @author 動力節(jié)點(diǎn)
 * @version 1.0
 * @className Wife
 * @since 1.0
 **/
public class Wife {
    private String name;
    private Husband husband;
    public void setName(String name) {
        this.name = name;
    }
    public String getName() {
        return name;
    }
    public void setHusband(Husband husband) {
        this.husband = husband;
    }
    // toString()方法重寫時需要注意:不能直接輸出husband,輸出husband.getName()。要不然會出現(xiàn)遞歸導(dǎo)致的棧內(nèi)存溢出錯誤。
    @Override
    public String toString() {
        return "Wife{" +
                "name='" + name + '\'' +
                ", husband=" + husband.getName() +
                '}';
    }
}
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    <bean id="husbandBean" class="com.powernode.spring6.bean.Husband" scope="singleton">
        <property name="name" value="張三"/>
        <property name="wife" ref="wifeBean"/>
    </bean>
    <bean id="wifeBean" class="com.powernode.spring6.bean.Wife" scope="singleton">
        <property name="name" value="小花"/>
        <property name="husband" ref="husbandBean"/>
    </bean>
</beans>
package com.powernode.spring6.test;
import com.powernode.spring6.bean.Husband;
import com.powernode.spring6.bean.Wife;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
 * @author 動力節(jié)點(diǎn)
 * @version 1.0
 * @className CircularDependencyTest
 * @since 1.0
 **/
public class CircularDependencyTest {
    @Test
    public void testSingletonAndSet(){
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml");
        Husband husbandBean = applicationContext.getBean("husbandBean", Husband.class);
        Wife wifeBean = applicationContext.getBean("wifeBean", Wife.class);
        System.out.println(husbandBean);
        System.out.println(wifeBean);
    }
}

通過測試得知:在singleton + set注入的情況下,循環(huán)依賴是沒有問題的。Spring可以解決這個問題。

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

Spring為什么可以解決set + singleton模式下循環(huán)依賴?
根本的原因在于:這種方式可以做到將“實(shí)例化Bean”和“給Bean屬性賦值”這兩個動作分開去完成。
實(shí)例化Bean的時候:調(diào)用無參數(shù)構(gòu)造方法來完成。此時可以先不給屬性賦值,可以提前將該Bean對象“曝光”給外界。
給Bean屬性賦值的時候:調(diào)用setter方法來完成。
兩個步驟是完全可以分離開去完成的,并且這兩步不要求在同一個時間點(diǎn)上完成。
也就是說,Bean都是單例的,我們可以先把所有的單例Bean實(shí)例化出來,放到一個集合當(dāng)中(我們可以稱之為緩存),所有的單例Bean全部實(shí)例化完成之后,以后我們再慢慢的調(diào)用setter方法給屬性賦值。這樣就解決了循環(huán)依賴的問題。
那么在Spring框架底層源碼級別上是如何實(shí)現(xiàn)的呢?請看:

在以上類中包含三個重要的屬性:
**Cache of singleton objects: bean name to bean instance. **單例對象的緩存:key存儲bean名稱,value存儲Bean對象【一級緩存】
**Cache of early singleton objects: bean name to bean instance. **早期單例對象的緩存:key存儲bean名稱,value存儲早期的Bean對象【二級緩存】
**Cache of singleton factories: bean name to ObjectFactory. **單例工廠緩存:key存儲bean名稱,value存儲該Bean對應(yīng)的ObjectFactory對象【三級緩存】
這三個緩存其實(shí)本質(zhì)上是三個Map集合。
我們再來看,在該類中有這樣一個方法addSingletonFactory(),這個方法的作用是:將創(chuàng)建Bean對象的ObjectFactory對象提前曝光。

再分析下面的源碼:

從源碼中可以看到,spring會先從一級緩存中獲取Bean,如果獲取不到,則從二級緩存中獲取Bean,如果二級緩存還是獲取不到,則從三級緩存中獲取之前曝光的ObjectFactory對象,通過ObjectFactory對象獲取Bean實(shí)例,這樣就解決了循環(huán)依賴的問題。
總結(jié):
Spring只能解決setter方法注入的單例bean之間的循環(huán)依賴。ClassA依賴ClassB,ClassB又依賴ClassA,形成依賴閉環(huán)。Spring在創(chuàng)建ClassA對象后,不需要等給屬性賦值,直接將其曝光到bean緩存當(dāng)中。在解析ClassA的屬性時,又發(fā)現(xiàn)依賴于ClassB,再次去獲取ClassB,當(dāng)解析ClassB的屬性時,又發(fā)現(xiàn)需要ClassA的屬性,但此時的ClassA已經(jīng)被提前曝光加入了正在創(chuàng)建的bean的緩存中,則無需創(chuàng)建新的的ClassA的實(shí)例,直接從緩存中獲取即可。從而解決循環(huán)依賴問題。

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

相關(guān)文章

  • Java的Object類九個方法技巧

    Java的Object類九個方法技巧

    這篇文章主要介紹了Java的Object類九個方法技巧,Java的Object?類的完整路徑是java.lang.Object?,是所有類的父類編譯,下文相關(guān)資料,需要的朋友可以參考一下
    2022-04-04
  • mybatis-plus自定義業(yè)務(wù)實(shí)現(xiàn)方式

    mybatis-plus自定義業(yè)務(wù)實(shí)現(xiàn)方式

    本文介紹了使用MyBatis-Plus(簡稱MP)進(jìn)行數(shù)據(jù)庫操作的實(shí)現(xiàn)步驟,包括創(chuàng)建實(shí)體類、Mapper接口和XML文件、Service接口和實(shí)現(xiàn)類,以及測試類,重點(diǎn)強(qiáng)調(diào)了業(yè)務(wù)層參數(shù)校驗、事務(wù)管理以及復(fù)雜SQL的處理方式
    2026-03-03
  • MyBatis 參數(shù)綁定的具體實(shí)現(xiàn)

    MyBatis 參數(shù)綁定的具體實(shí)現(xiàn)

    本文主要介紹了MyBatis 參數(shù)綁定的具體實(shí)現(xiàn),包括默認(rèn)參數(shù)名、@Param注解和POJO/DTO對象三種方式,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2026-01-01
  • 解決Kibana報錯[security_exception] current license is non-compliant for [security]問題

    解決Kibana報錯[security_exception] current license&nbs

    ElasticSearch 5.1.1因安全許可證過期報錯,解決方法:官網(wǎng)申請新許可證,下載JSON文件并上傳至服務(wù)器,執(zhí)行代碼時切換root權(quán)限,配置host為服務(wù)器IP,端口9200,替換原license文件
    2025-07-07
  • SpringBoot多環(huán)境切換的靈活配置詳細(xì)教程

    SpringBoot多環(huán)境切換的靈活配置詳細(xì)教程

    在真實(shí)項目開發(fā)的時候,一定會有多個環(huán)境,下面這篇文章主要給大家介紹了關(guān)于SpringBoot多環(huán)境切換靈活配置的相關(guān)資料,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2024-04-04
  • SpringBoot讀取Resource下文件的4種方法

    SpringBoot讀取Resource下文件的4種方法

    這篇文章主要介紹了SpringBoot讀取Resource下文件的4種方法小結(jié),具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-07-07
  • Spring MVC實(shí)現(xiàn)的登錄攔截器代碼分享

    Spring MVC實(shí)現(xiàn)的登錄攔截器代碼分享

    這篇文章主要介紹了Spring MVC實(shí)現(xiàn)的登錄攔截器代碼分享,涉及攔截器的簡單介紹,攔截器和過濾器的區(qū)以及攔截器實(shí)現(xiàn)代碼等相關(guān)內(nèi)容,這里分享給大家,供需要的朋友參考。
    2017-10-10
  • Springboot的application.properties或application.yml環(huán)境的指定運(yùn)行與配置方式

    Springboot的application.properties或application.yml環(huán)境的指定運(yùn)行與配置方

    本文主要介紹了Spring?Boot中配置文件的多種使用方式,包括配置文件的命名、激活、路徑指定以及優(yōu)先級,并結(jié)合示例進(jìn)行了詳細(xì)說明
    2025-11-11
  • 詳解Java異常處理中throw與throws關(guān)鍵字的用法區(qū)別

    詳解Java異常處理中throw與throws關(guān)鍵字的用法區(qū)別

    這篇文章主要介紹了詳解Java異常處理中throw與throws關(guān)鍵字的用法區(qū)別,這也是Java面試題目中的常客,需要的朋友可以參考下
    2015-11-11
  • Java使用TCP實(shí)現(xiàn)在線聊天的示例代碼

    Java使用TCP實(shí)現(xiàn)在線聊天的示例代碼

    這篇文章主要介紹了Java使用TCP實(shí)現(xiàn)在線聊天的示例代碼,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-01-01

最新評論

布尔津县| 鄂州市| 团风县| 醴陵市| 南投县| 鹤岗市| 香河县| 靖安县| 仙游县| 广灵县| 八宿县| 肃北| 黄浦区| 大渡口区| 荆门市| 汉沽区| 礼泉县| 江川县| 平度市| 永吉县| 安多县| 靖安县| 澄城县| 崇左市| 唐河县| 连云港市| 塔城市| 都江堰市| 溧水县| 井研县| 太原市| 吉安市| 新龙县| 邮箱| 黄浦区| 湘潭县| 墨脱县| 泗水县| 石楼县| 上杭县| 丹江口市|