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

Spring中的循環(huán)依賴詳解

 更新時(shí)間:2023年09月14日 08:47:52   作者:這堆干貨有點(diǎn)猛  
這篇文章主要介紹了Spring中的循環(huán)依賴詳解,  Spring 框架是一個(gè)流行的Java應(yīng)用程序框架,它提供了許多強(qiáng)大的功能,如依賴注入和面向切面編程,然而在使用 Spring 框架時(shí),我們可能會(huì)遇到循環(huán)依賴的問(wèn)題,需要的朋友可以參考下

Spring 框架是一個(gè)流行的Java應(yīng)用程序框架,它提供了許多強(qiáng)大的功能,如依賴注入和面向切面編程。然而在使用 Spring 框架時(shí),我們可能會(huì)遇到循環(huán)依賴的問(wèn)題。

這種情況發(fā)生在兩個(gè)或多個(gè) Bean 之間相互依賴的情況下,其中一個(gè) Bean 依賴于另一個(gè) Bean,而另一個(gè) Bean 又依賴于第一個(gè) Bean

在這種情況下,Spring 框架需要解決循環(huán)依賴的問(wèn)題,否則應(yīng)用程序可能會(huì)出現(xiàn)死鎖或其他錯(cuò)誤。

本文將探討 Spring 框架是如何解決循環(huán)依賴的問(wèn)題,以及它是如何工作的。我們將分析 Spring 框架的源代碼,并提供一些示例來(lái)說(shuō)明 Spring 框架如何解決循環(huán)依賴的問(wèn)題。

解決循環(huán)依賴的原理

在 Spring 框架中,當(dāng)兩個(gè)或多個(gè) Bean 之間相互依賴時(shí), Spring 框架會(huì)創(chuàng)建一個(gè)代理對(duì)象,該代理對(duì)象負(fù)責(zé)管理這些 Bean 之間的依賴關(guān)系。這個(gè)代理對(duì)象被稱為“early proxy”或“exposed proxy”。

當(dāng)一個(gè) Bean 需要訪問(wèn)另一個(gè) Bean 時(shí), Spring 框架會(huì)通過(guò)代理對(duì)象來(lái)獲取該 Bean。這個(gè)代理對(duì)象負(fù)責(zé)保證 Bean 的實(shí)例化順序,確保每個(gè) Bean 都只被實(shí)例化一次,并且在所有依賴關(guān)系被滿足之前,不會(huì)暴露任何未實(shí)例化的 Bean 。

Spring 框架解決循環(huán)依賴的過(guò)程如下

  • 當(dāng) Spring 框架啟動(dòng)時(shí),它會(huì)掃描應(yīng)用程序中的所有 Bean,并將它們注冊(cè)到一個(gè) Bean Factory中。
  • 當(dāng)一個(gè) Bean 被實(shí)例化時(shí)Spring 框架會(huì)檢查它是否有任何依賴關(guān)系。
  • 如果 Bean 有依賴關(guān)系,則 Spring 框架會(huì)檢查這些依賴關(guān)系是否已經(jīng)被創(chuàng)建。
  • 如果依賴關(guān)系已經(jīng)被創(chuàng)建,則 Spring 框架會(huì)將依賴關(guān)系注入到 Bean 中,并返回該 Bean 的實(shí)例。
  • 如果依賴關(guān)系還沒(méi)有被創(chuàng)建,則 Spring 框架會(huì)創(chuàng)建一個(gè)代理對(duì)象(通過(guò) getEarlyBeanReference 方法),并將該代理對(duì)象暴露給該 Bean。
  • 當(dāng)依賴關(guān)系被創(chuàng)建時(shí),Spring 框架會(huì)使用代理對(duì)象來(lái)獲取依賴關(guān)系,并將依賴關(guān)系注入到 Bean 中。
  • 當(dāng)所有依賴關(guān)系都被滿足時(shí),Spring 框架會(huì)返回該 Bean 的實(shí)例。

源碼解析

為了更好地理解 Spring 框架如何解決循環(huán)依賴的問(wèn)題,我們將分析 Spring 框架的源代碼。

下面是一個(gè)簡(jiǎn)單的示例,演示了 Spring 框架如何解決循環(huán)依賴的問(wèn)題。

public class A {
    private B b;
    public A() {}
    public void setB(B b) {
        this.b = b;
    }
}
public class B {
    private A a;
    public B() {}
    public void setA(A a) {
        this.a = a;
    }
}
@Configuration
public class AppConfig {
    @Bean
    public A a() {
        return new A();
    }
    @Bean
    public B b() {
        return new B();
    }
}

在這個(gè)示例中,類A依賴于類B,而類B又依賴于類A。因此,這個(gè)示例展示了一個(gè)循環(huán)依賴的情況。

當(dāng)應(yīng)用程序啟動(dòng)時(shí),Spring 框架會(huì)掃描所有的 Bean ,并將它們注冊(cè)到一個(gè)BeanFactory中。

當(dāng) BeanFactory創(chuàng)建 Bean 時(shí),它會(huì)檢查 Bean 是否有任何依賴關(guān)系。

在這個(gè)示例中,當(dāng) BeanFactory 創(chuàng)建 A 和 B 時(shí),它會(huì)檢查它們之間的依賴關(guān)系。由于 A 依賴于 B,而 B 又依賴于 A,因此存在循環(huán)依賴的問(wèn)題。

為了解決這個(gè)問(wèn)題,Spring 框架會(huì)創(chuàng)建一個(gè)代理對(duì)象,該代理對(duì)象負(fù)責(zé)管理A和B之間的依賴關(guān)系。在這個(gè)示例中,當(dāng) BeanFactory 創(chuàng)建 A 時(shí),它會(huì)創(chuàng)建一個(gè)代理對(duì)象,并將該代理對(duì)象暴露給A。當(dāng)BeanFactory創(chuàng)建B時(shí),它會(huì)創(chuàng)建一個(gè)代理對(duì)象,并將該代理對(duì)象暴露給 B。這樣,A和B就可以通過(guò)代理對(duì)象來(lái)訪問(wèn)彼此,而不會(huì)出現(xiàn)循環(huán)依賴的問(wèn)題。

下面是 Spring 框架解決循環(huán)依賴的源碼示例:

首先 Spring 框架會(huì)從緩存中獲取需要的 bean:

protected Object getSingleton(String beanName, boolean allowEarlyReference) {
    Object singletonObject = this.singletonObjects.get(beanName);
    if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
        synchronized (this.singletonObjects) {
            singletonObject = this.earlySingletonObjects.get(beanName);
            if (singletonObject == null && allowEarlyReference) {
                ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
                if (singletonFactory != null) {
                    singletonObject = singletonFactory.getObject();
                    this.earlySingletonObjects.put(beanName, singletonObject);
                    this.singletonFactories.remove(beanName);
                }
            }
        }
    }
    return (singletonObject != NULL_OBJECT ? singletonObject : null);
}

上面代碼中,框架分別從 singletonObjects、earlySingletonObjects、singletonFactories 中獲取需要的實(shí)例,如果獲取不到,就就行創(chuàng)建,在創(chuàng)建的過(guò)程中如果發(fā)現(xiàn)需要處理循環(huán)依賴,就會(huì)調(diào)用下面方法獲取代理對(duì)象:

private Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) {
    Object exposedObject = bean;
    if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
        for (BeanPostProcessor bp : getBeanPostProcessors()) {
            if (bp instanceof SmartInstantiationAwareBeanPostProcessor) {
                SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp;
                exposedObject = ibp.getEarlyBeanReference(exposedObject, beanName);
                if (exposedObject == null) {
                    return exposedObject;
                }
            }
        }
    }
    return exposedObject;
}

在這個(gè)示例中,getEarlyBeanReference() 方法是 Spring 框架用來(lái)獲取代理對(duì)象的方法。該方法首先檢查 Bean 是否為合成的 Bean ,然后檢查該 Bean 是否有任何實(shí)例化后的 Bean 后處理器。如果 Bean 有實(shí)例化后的 Bean 后處理器,則 Spring 框架會(huì)使用這些 Bean 后處理器來(lái)獲取代理對(duì)象。

spring.png

總結(jié)

在本文中,我們探討了 Spring 框架是如何解決循環(huán)依賴的問(wèn)題的。

我們分析了 Spring 框架的源代碼,并提供了一些示例來(lái)說(shuō)明 Spring 框架如何解決循環(huán)依賴的問(wèn)題。

總之, Spring 框架通過(guò)創(chuàng)建代理對(duì)象來(lái)解決循環(huán)依賴的問(wèn)題,該代理對(duì)象負(fù)責(zé)管理 Bean 之間的依賴關(guān)系,并確保每個(gè) Bean 都只被實(shí)例化一次。

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

相關(guān)文章

  • java與js代碼互調(diào)示例代碼

    java與js代碼互調(diào)示例代碼

    用到j(luò)ava和js方法互調(diào),在用HTML5做跨平臺(tái)應(yīng)用開(kāi)發(fā)時(shí)經(jīng)常會(huì)用到,在這里分享一些自己在實(shí)際開(kāi)發(fā)過(guò)程中的用法,希望對(duì)初學(xué)者有所幫助
    2013-07-07
  • springboot 整合 seata的配置過(guò)程

    springboot 整合 seata的配置過(guò)程

    本文給大家介紹springboot 整合 seata的配置過(guò)程,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友參考下吧
    2021-08-08
  • 一篇文章帶你深入了解javaIO基礎(chǔ)

    一篇文章帶你深入了解javaIO基礎(chǔ)

    這篇文章主要介紹了java 基礎(chǔ)知識(shí)之IO總結(jié)的相關(guān)資料,Java中的I/O分為兩種類型,一種是順序讀取,一種是隨機(jī)讀取,需要的朋友可以參考下,希望對(duì)你有幫助
    2021-08-08
  • futuretask用法及使用場(chǎng)景介紹

    futuretask用法及使用場(chǎng)景介紹

    這篇文章主要介紹了futuretask用法及使用場(chǎng)景介紹,小編覺(jué)得挺不錯(cuò)的,這里分享給大家,供大家參考。
    2017-10-10
  • SpringMVC互聯(lián)網(wǎng)軟件架構(gòu)REST使用詳解

    SpringMVC互聯(lián)網(wǎng)軟件架構(gòu)REST使用詳解

    這篇文章主要為大家詳細(xì)介紹了SpringMVC互聯(lián)網(wǎng)軟件架構(gòu)REST的相關(guān)資料,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-03-03
  • Java的@Transactional、@Aysnc、事務(wù)同步問(wèn)題詳解

    Java的@Transactional、@Aysnc、事務(wù)同步問(wèn)題詳解

    這篇文章主要介紹了Java的@Transactional、@Aysnc、事務(wù)同步問(wèn)題詳解,現(xiàn)在我們需要在一個(gè)業(yè)務(wù)方法中插入一個(gè)用戶,這個(gè)業(yè)務(wù)方法我們需要加上事務(wù),然后插入用戶后,我們要異步的方式打印出數(shù)據(jù)庫(kù)中所有存在的用戶,需要的朋友可以參考下
    2023-11-11
  • Java方法重寫_動(dòng)力節(jié)點(diǎn)Java學(xué)院整理

    Java方法重寫_動(dòng)力節(jié)點(diǎn)Java學(xué)院整理

    在Java和其他一些高級(jí)面向?qū)ο蟮木幊陶Z(yǔ)言中,子類可繼承父類中的方法,而不需要重新編寫相同的方法。但有時(shí)子類并不想原封不動(dòng)地繼承父類的方法,而是想作一定的修改,這就需要采用方法的重寫。方法重寫又稱方法覆蓋,下文給大家介紹java方法重寫及重寫規(guī)則,一起學(xué)習(xí)吧
    2017-04-04
  • 詳細(xì)圖解Java中字符串的初始化

    詳細(xì)圖解Java中字符串的初始化

    字符串廣泛應(yīng)用在Java編程中,在Java中字符串屬于對(duì)象,Java提供了String類來(lái)創(chuàng)建和操作字符串,下面這篇文章主要給大家介紹了Java中字符串初始化的相關(guān)資料,需要的朋友可以參考下
    2021-08-08
  • 利用Spring JPA中的@Version注解實(shí)現(xiàn)樂(lè)觀鎖

    利用Spring JPA中的@Version注解實(shí)現(xiàn)樂(lè)觀鎖

    樂(lè)觀鎖是數(shù)據(jù)庫(kù)和應(yīng)用程序中使用的一種并發(fā)控制策略,用于在多個(gè)事務(wù)嘗試更新單個(gè)記錄時(shí)確保數(shù)據(jù)完整性,Java Persistence API (JPA) 提供了一種借助@Version注解在 Java 應(yīng)用程序中實(shí)現(xiàn)樂(lè)觀鎖的機(jī)制,文中有詳細(xì)的代碼示例供大家參考,需要的朋友可以參考下
    2023-11-11
  • MyBatis 接收數(shù)據(jù)庫(kù)中沒(méi)有的字段的解決

    MyBatis 接收數(shù)據(jù)庫(kù)中沒(méi)有的字段的解決

    這篇文章主要介紹了MyBatis 接收數(shù)據(jù)庫(kù)中沒(méi)有的字段的解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-03-03

最新評(píng)論