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

關(guān)于spring三級(jí)緩存的解讀

 更新時(shí)間:2025年02月12日 09:28:45   作者:ambity_lyf  
Spring三級(jí)緩存解決循環(huán)依賴、AOP和多線程問(wèn)題,包括singletonObjects、earlySingletonObjects和singletonFactories三層緩存,通過(guò)不同方法獲取bean并解決這些問(wèn)題

spring三級(jí)緩存的解讀

spring 中為了解決 B的重復(fù)利用,A 依賴B 的循環(huán)依賴,aop 問(wèn)題,多線程可能拿到不完整的bean 的問(wèn)題引入了3層緩存,分別是

/** Cache of singleton objects: bean name to bean instance. */
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);

/** Cache of early singleton objects: bean name to bean instance. */
private final Map<String, Object> earlySingletonObjects = new HashMap<>(16);

/** Cache of singleton factories: bean name to ObjectFactory. */
private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);
  • singletonObjects 用于存放單例bean 實(shí)例
  • earlySingletonObjects 用于存放早期的bean 實(shí)例
  • singletonFactories 用于存放簡(jiǎn)單工廠實(shí)例

從3級(jí)緩存中 獲取bean 的方法有如下兩個(gè)

1.從緩存中獲取,主要用來(lái)解決循環(huán)依賴問(wèn)題

protected Object getSingleton(String beanName, boolean allowEarlyReference) {
   // 這里不用考慮指令重排,因?yàn)?bean 初始化完成后才會(huì)放入map
   Object singletonObject = this.singletonObjects.get(beanName);
   if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
      // 加鎖,與另一個(gè)getSingleton 方法 互斥訪問(wèn),保證并發(fā)情況下獲取到不完整的bean
      synchronized (this.singletonObjects) {
         singletonObject = this.earlySingletonObjects.get(beanName);
         if (singletonObject == null && allowEarlyReference) {
            // 獲取工廠bean ,因?yàn)榭赡苁莂op 生成的代理,這里二級(jí)和三級(jí)緩存保證獲取到的bean 是最后的完整bean
            ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
            if (singletonFactory != null) {
               singletonObject = singletonFactory.getObject();
               // 放入 二級(jí)緩存中,從3級(jí)緩存中移除
               this.earlySingletonObjects.put(beanName, singletonObject);
               this.singletonFactories.remove(beanName);
            }
         }
      }
   }
   return singletonObject;
}

2.創(chuàng)建bean 的真正邏輯

public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
   Assert.notNull(beanName, "Bean name must not be null");
   synchronized (this.singletonObjects) {
      // 再次從一級(jí)緩存中獲取,因?yàn)槎嗑€程加載同一個(gè)bean 時(shí),
      //相當(dāng)于 雙重檢查
      Object singletonObject = this.singletonObjects.get(beanName);
      if (singletonObject == null) {
         if (this.singletonsCurrentlyInDestruction) {
            throw new BeanCreationNotAllowedException(beanName,
                  "Singleton bean creation not allowed while singletons of this factory are in destruction " +
                  "(Do not request a bean from a BeanFactory in a destroy method implementation!)");
         }
         if (logger.isDebugEnabled()) {
            logger.debug("Creating shared instance of singleton bean '" + beanName + "'");
         }
         // 標(biāo)記bean 正在創(chuàng)建
         beforeSingletonCreation(beanName);
         boolean newSingleton = false;
         boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
         if (recordSuppressedExceptions) {
            this.suppressedExceptions = new LinkedHashSet<>();
         }
         try {
            singletonObject = singletonFactory.getObject();
            newSingleton = true;
         }
         catch (IllegalStateException ex) {
            // Has the singleton object implicitly appeared in the meantime ->
            // if yes, proceed with it since the exception indicates that state.
            singletonObject = this.singletonObjects.get(beanName);
            if (singletonObject == null) {
               throw ex;
            }
         }
         catch (BeanCreationException ex) {
            if (recordSuppressedExceptions) {
               for (Exception suppressedException : this.suppressedExceptions) {
                  ex.addRelatedCause(suppressedException);
               }
            }
            throw ex;
         }
         finally {
            if (recordSuppressedExceptions) {
               this.suppressedExceptions = null;
            }
            afterSingletonCreation(beanName);
         }
         if (newSingleton) {
            addSingleton(beanName, singletonObject);
         }
      }
      return singletonObject;
   }
}

我們先假設(shè)不存在aop 與多線程競(jìng)爭(zhēng)的情況,此時(shí)我們只需要一級(jí)緩存就可以解決循環(huán)依賴的問(wèn)題

  • 1.構(gòu)造bean A ->
  • 2.把A 放入 map1 ->
  • 3. 填充A的屬性 ->
  • 4.創(chuàng)建bean B ->
  • 5.填充B->
  • 6.從緩存中拿到A->
  • 7.返回B ->
  • 8返回A

即不存在aop且不考慮多線程的情況下,只要一個(gè)map1 我們就能解決循環(huán)依賴的問(wèn)題

3.現(xiàn)在我們考慮aop

假設(shè)A 有屬性B ,B 有屬性A ,且我們對(duì)A 做了aop,在創(chuàng)建B 的時(shí)候我們希望拿到的是A 的aop 代理對(duì)象,此時(shí)假設(shè)填充B 的時(shí)候獲取A ,

假設(shè)如果我們用一層緩存解決?

可以對(duì)是否aop 代理過(guò)存儲(chǔ)一個(gè)標(biāo)志位,此時(shí)必然在后面獲取bean 的時(shí)候都要多一層判斷,所以此時(shí)需要二層緩存來(lái)解決

一層存放aop 代理過(guò)的對(duì)象或不需要aop 的對(duì)象,一層存放非aop 對(duì)象,即創(chuàng)建工廠。

4.我們?cè)倏紤]并發(fā)的情況,即多線程獲取一個(gè)單例

這里如果熟悉單例模式的創(chuàng)建過(guò)程,就不難理解第二個(gè)方法中的synchronized 與加鎖后再次嘗試從一級(jí)緩存中獲取,把第一個(gè)方法可以看作第一次非空判斷,那么就是雙重鎖檢查保證單例。但是只做了雙重鎖檢查保證單例可以支持多線程操作嗎?

答案是否定的,假設(shè)我們?yōu)榱私鉀Qaop 使用了二層緩存,對(duì)于A 來(lái)說(shuō) 并沒(méi)有完全完成賦值和初始化的操作,但是由于A 依賴B ,B依賴于A的aop 代理對(duì)象,此時(shí)A 已經(jīng)在一級(jí)中了,那么線程2邊能從map1 中獲取到 對(duì)象A,(當(dāng)然你也可以對(duì)整個(gè)創(chuàng)建過(guò)程加鎖,那么就不存在多線程問(wèn)題)。但是此時(shí)A 對(duì)象并沒(méi)有完成賦值與init 的方法執(zhí)行,這樣很容易造成線程2 的異常,所以還需要一層緩存將完成整個(gè)創(chuàng)建過(guò)程的bean ,與沒(méi)有創(chuàng)建完成的純潔bean 隔離開(kāi),所以才有了3級(jí)緩存。

此時(shí)再考慮3級(jí)緩存的獲取,基于并發(fā)的考慮就不難理解第一個(gè)方法為何要synchronized 了,即保證并發(fā)下,緩存只在一層緩存中存在。

綜上來(lái)說(shuō),我的理解,aop 問(wèn)題需要兩層緩存來(lái)解決,而考慮多線程并發(fā)的情況下,所以需要三層緩存來(lái)解決。

總結(jié)

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

相關(guān)文章

  • 詳解spring注解式參數(shù)校驗(yàn)

    詳解spring注解式參數(shù)校驗(yàn)

    本篇文章主要介紹了詳解spring注解式參數(shù)校驗(yàn),小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2017-06-06
  • JavaScript中的isTrusted屬性及其應(yīng)用場(chǎng)景詳解

    JavaScript中的isTrusted屬性及其應(yīng)用場(chǎng)景詳解

    在現(xiàn)代 Web 開(kāi)發(fā)中,JavaScript 是構(gòu)建交互式應(yīng)用的核心語(yǔ)言,隨著前端技術(shù)的不斷發(fā)展,開(kāi)發(fā)者需要處理越來(lái)越多的復(fù)雜場(chǎng)景,例如事件處理、數(shù)據(jù)傳遞和狀態(tài)管理等,本文將通過(guò)一個(gè)實(shí)際案例,深入探討 isTrusted 屬性的來(lái)源、作用,需要的朋友可以參考下
    2025-01-01
  • java中l(wèi)ong和Long有什么區(qū)別詳解

    java中l(wèi)ong和Long有什么區(qū)別詳解

    這篇文章主要介紹了Java中l(wèi)ong和Long是基本數(shù)據(jù)類型和包裝數(shù)據(jù)類型的區(qū)別,包括默認(rèn)值、內(nèi)存占用、使用場(chǎng)景、方法支持以及裝箱和拆箱,包裝數(shù)據(jù)類型如Integer提供了許多有用的方法,需要的朋友可以參考下
    2025-02-02
  • SpringBoot創(chuàng)建自定義starter詳解

    SpringBoot創(chuàng)建自定義starter詳解

    這篇文章主要介紹了SpringBoot創(chuàng)建自定義starter詳解,Starter是Spring Boot中的一個(gè)非常重要的概念,Starter相當(dāng)于模塊,它能將模塊所需的依賴整合起來(lái)并對(duì)模塊內(nèi)的Bean根據(jù)環(huán)境(條件)進(jìn)行自動(dòng)配置,需要的朋友可以參考下
    2024-01-01
  • Java解析XML文件開(kāi)源庫(kù)DOM4J

    Java解析XML文件開(kāi)源庫(kù)DOM4J

    dom4j是一個(gè)Java的XML API,是jdom的升級(jí)品,用來(lái)讀寫(xiě)XML文件的。dom4j是一個(gè)十分優(yōu)秀的JavaXML API,具有性能優(yōu)異、功能強(qiáng)大和極其易使用的特點(diǎn),它的性能超過(guò)sun公司官方的dom技術(shù),同時(shí)它也是一個(gè)開(kāi)放源代碼的軟件
    2023-01-01
  • 詳細(xì)聊聊Mybatis中萬(wàn)能的Map

    詳細(xì)聊聊Mybatis中萬(wàn)能的Map

    最近有個(gè)需求,就是使用mybatis時(shí),向mysql中插入數(shù)據(jù),其參數(shù)為map類型,下面這篇文章主要給大家介紹了關(guān)于Mybatis中萬(wàn)能的Map的相關(guān)資料,需要的朋友可以參考下
    2021-12-12
  • 徹底解決Spring mvc中時(shí)間的轉(zhuǎn)換和序列化等問(wèn)題

    徹底解決Spring mvc中時(shí)間的轉(zhuǎn)換和序列化等問(wèn)題

    這篇文章主要介紹了徹底解決Spring mvc中時(shí)間的轉(zhuǎn)換和序列化等問(wèn)題,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-09-09
  • Java中File與byte[]的互轉(zhuǎn)方式

    Java中File與byte[]的互轉(zhuǎn)方式

    這篇文章主要介紹了Java中File與byte[]的互轉(zhuǎn)方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-05-05
  • springboot2.1.3配置sftp自定義sftp連接池的詳細(xì)過(guò)程

    springboot2.1.3配置sftp自定義sftp連接池的詳細(xì)過(guò)程

    這篇文章主要介紹了springboot2.1.3配置sftp自定義sftp連接池的詳細(xì)過(guò)程,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2021-08-08
  • java實(shí)現(xiàn)操作系統(tǒng)的短進(jìn)程作業(yè)調(diào)度示例分享

    java實(shí)現(xiàn)操作系統(tǒng)的短進(jìn)程作業(yè)調(diào)度示例分享

    java編寫(xiě)的實(shí)現(xiàn)了操作系統(tǒng)中的短作業(yè)進(jìn)程,可以實(shí)現(xiàn)幾道作業(yè)同時(shí)作業(yè)調(diào)度
    2014-02-02

最新評(píng)論