亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

Spring為何要用三級緩存來解決循環(huán)依賴問題

 更新時間:2020年10月25日 15:03:45   作者:zero  
這篇文章主要給大家介紹了關(guān)于Spring為何要用三級緩存來解決循環(huán)依賴問題的相關(guān)資料,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧

我們都知道Spring為了解決循環(huán)依賴使用了三級緩存

Spring三級緩存

一級緩存singletonObjects

用于保存BeanName和創(chuàng)建bean實例之間的關(guān)系,beanName -> bean instance

private final Map<String, Object> singletonObjects = new ConcurrentHashMap(256);

二級緩存earlySingletonObjects

保存提前曝光的單例bean對象

private final Map<String, Object> earlySingletonObjects = new HashMap<>(16);

三級緩存singletonFactories

保存beanName和創(chuàng)建bean實例之間的關(guān)系,與singletonObjects不同的地方在于,當(dāng)一個單例bean被放到這里面后,bean在創(chuàng)建過程中,可以通過getBean方法獲取到,目的是用來檢測循環(huán)引用

private final Map<String, Object> singletonFactories = new HashMap(16);

在創(chuàng)建bean的時候,首先從緩存中獲取單例的bean,這個緩存就是singletonObjects,如果獲取不到且bean正在創(chuàng)建中,就再從earlySingletonObjects中獲取,如果還是獲取不到且允許從singletonFactories中通過getObject拿到對象,就從singletonFactories中獲取,如果獲取到了就存入earlySingletonObjects并從singletonFactories中移除。

為什么要使用三級緩存?

一級緩存

首先我們看看一級緩存行不行,如果只留第一級緩存,那么單例的Bean都存在singletonObjects 中,Spring循環(huán)依賴主要基于Java引用傳遞,當(dāng)獲取到對象時,對象的field或者屬性可以延后設(shè)置,理論上可以,但是如果延后設(shè)置出了問題,就會導(dǎo)致完整的Bean和不完整的Bean都在一級緩存中,這個引用時就有空指針的可能,所以一級緩存不行,至少要有singletonObjects 和earlySingletonObjects 兩級。

兩級緩存

那么我們再看看兩級緩存行不行

現(xiàn)在有A的field或者setter依賴B的實例對象,同時B的field或者setter依賴了A的實例,A首先開始創(chuàng)建,并將自己暴露到 earlySingletonObjects 中,開始填充屬性,此時發(fā)現(xiàn)自己依賴B的屬性,嘗試去get(B),發(fā)現(xiàn)B還沒有被創(chuàng)建,所以開始創(chuàng)建B,在進行屬性填充時初始化A,就從earlySingletonObjects 中獲取到了實例化但沒有任何屬性的A,B拿到A后完成了初始化階段,將自己放到singletonObjects中,此時返回A,A拿到B的對象繼續(xù)完成初始化,完成后將自己放到singletonObjects中,由A與B中所表示的A的屬性地址是一樣的,所以A的屬性填充完后,B也獲取了A的屬性,這樣就解決了循環(huán)的問題。

似乎完美解決,如果就這么使用的話也沒什么問題,但是再加上AOP情況就不同了,被AOP增強的Bean會在初始化后代理成為一個新的對象,也就是說:

如果有AOP,A依賴于B,B依賴于A,A實例化完成暴露出去,開始注入屬性,發(fā)現(xiàn)引用B,B開始實例化,使用A暴露的對象,初始化完成后封裝成代理對象,A再將代理后的B注入,再做代理,那么代理A中的B就是代理后的B,但是代理后的B中的A是沒用代理的A。

顯然這是不對的,所以在Spring中存在第三級緩存,在創(chuàng)建對象時判斷是否是單例,允許循環(huán)依賴,正在創(chuàng)建中,就將其從earlySingletonObjects中移除掉,并在singletonFactories放入新的對象,這樣后續(xù)再查詢beanName時會走到singletonFactory.getObject(),其中就會去調(diào)用各個beanPostProcessor的getEarlyBeanReference方法,返回的對象就是代理后的對象。

public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactory
  implements AutowireCapableBeanFactory { 
 
  // Eagerly cache singletons to be able to resolve circular references
  // even when triggered by lifecycle interfaces like BeanFactoryAware.
  boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
    isSingletonCurrentlyInCreation(beanName));
  if (earlySingletonExposure) {
   if (logger.isDebugEnabled()) {
    logger.debug("Eagerly caching bean '" + beanName +
      "' to allow for resolving potential circular references");
   }
   addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
  }

  /**
  * Add the given singleton factory for building the specified singleton
  * if necessary.
  * <p>To be called for eager registration of singletons, e.g. to be able to
  * resolve circular references.
  * @param beanName the name of the bean
  * @param singletonFactory the factory for the singleton object
  */
 protected void addSingletonFactory(String beanName, ObjectFactory<?> singletonFactory) {
  Assert.notNull(singletonFactory, "Singleton factory must not be null");
  synchronized (this.singletonObjects) {
   if (!this.singletonObjects.containsKey(beanName)) {
    this.singletonFactories.put(beanName, singletonFactory);
    this.earlySingletonObjects.remove(beanName);
    this.registeredSingletons.add(beanName);
   }
  }
 }

總結(jié)

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

相關(guān)文章

  • SpringCloud Gateway網(wǎng)關(guān)功能介紹與使用

    SpringCloud Gateway網(wǎng)關(guān)功能介紹與使用

    SpringCloud Gateway 是 Spring Cloud 的一個全新項目,它旨在為微服務(wù)架構(gòu)提供一種簡單有效的統(tǒng)一的 API 路由管理方式。這篇文章主要介紹了SpringCloud Gateway網(wǎng)關(guān)作用,需要的朋友可以參考下
    2022-12-12
  • springboot解決前后端分離時的跨域問題

    springboot解決前后端分離時的跨域問題

    這篇文章主要介紹了springboot如何解決前后端分離時的跨域問題,幫助大家更好的理解和學(xué)習(xí)使用springboot,感興趣的朋友可以了解下
    2021-04-04
  • 基于Java實現(xiàn)互聯(lián)網(wǎng)實時聊天系統(tǒng)(附源碼)

    基于Java實現(xiàn)互聯(lián)網(wǎng)實時聊天系統(tǒng)(附源碼)

    Netty?是一個利用?Java?的高級網(wǎng)絡(luò)的能力,隱藏其背后的復(fù)雜性而提供一個易于使用的?API?的客戶端/服務(wù)器框架。本文將利用它實現(xiàn)互聯(lián)網(wǎng)實時聊天系統(tǒng),感興趣的可以了解一下
    2022-09-09
  • Java操作數(shù)據(jù)庫(行級鎖,for update)

    Java操作數(shù)據(jù)庫(行級鎖,for update)

    這篇文章主要介紹了Java操作數(shù)據(jù)庫(行級鎖,for update),文章圍繞Java操作數(shù)據(jù)庫的相關(guān)資料展開詳細內(nèi)容,需要的小伙伴可以參考一下,希望對你有所幫助
    2021-12-12
  • mybatis中如何實現(xiàn)一個標(biāo)簽執(zhí)行多個sql語句

    mybatis中如何實現(xiàn)一個標(biāo)簽執(zhí)行多個sql語句

    這篇文章主要介紹了mybatis中如何實現(xiàn)一個標(biāo)簽執(zhí)行多個sql語句問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-04-04
  • Fluent Mybatis實際開發(fā)中的優(yōu)勢對比

    Fluent Mybatis實際開發(fā)中的優(yōu)勢對比

    本文給大家介紹如何通過IQuery和IUpdate定義強大的動態(tài)SQL語句,給大家分享Fluent Mybatis實際開發(fā)中的優(yōu)勢講解,感興趣的朋友一起看看吧
    2021-08-08
  • 如何在Java SpringBoot項目中配置動態(tài)數(shù)據(jù)源你知道嗎

    如何在Java SpringBoot項目中配置動態(tài)數(shù)據(jù)源你知道嗎

    這篇文章主要介紹了SpringBoot如何在運行時動態(tài)添加數(shù)據(jù)源,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2021-09-09
  • Maven中的dependencyManagement 實例詳解

    Maven中的dependencyManagement 實例詳解

    dependencyManagement的中文意思就是依賴關(guān)系管理,它就是為了能通更好統(tǒng)一管理項目的版本號和各種jar版本號,可以更加方便升級,解決包沖突問題,這篇文章主要介紹了Maven中的dependencyManagement 實例詳解,需要的朋友可以參考下
    2024-02-02
  • Spring對靜態(tài)變量無法注入的解決方案

    Spring對靜態(tài)變量無法注入的解決方案

    這篇文章主要介紹了使用Spring對靜態(tài)變量無法注入的解決方案,具有很好的參考價值,希望對大家有所幫助。
    2021-07-07
  • Java中的接口和抽象類用法實例詳解

    Java中的接口和抽象類用法實例詳解

    這篇文章主要介紹了Java中的接口和抽象類用法,結(jié)合實例形式較為詳細的分析了Java中關(guān)于接口和抽象類的概念、定義、用法與相關(guān)注意事項,需要的朋友可以參考下
    2015-12-12

最新評論