成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

Spring如何使用三級緩存解決循環依賴

開發 前端
三級緩存中存儲的是單利工廠緩存,通過調用該對象的 GetObject 方法,可以獲取到早期暴露出去的 Bean;在該 Bean 要被其他 Bean 引用時,Spring 就會用工廠對象創建出該 Bean 的實例對象,最終當該 Bean 完成構造的所有步驟后就會將該 Bean 放入到一級緩存中。

1. 前言

在日常開發中,Bean之間的循環依賴非常常見,Spring 已經幫我們做到使用無感知處理,那么 Spring 是如何實現的呢?

2. 循環依賴簡介

2.1 什么是循環依賴

循環依賴是指兩個或多個對象存在相互依賴、相互引用的關系,而這種引用形成一個環時,就會出現循環引用,如圖:

圖片圖片

public class PersonA { 
  @Autowired
  private PersonB personB;
}
public class PersonB {
  @Autowired
  private PersonA personA;
}

2.2 Spring 處理循環依賴的前提條件

1.相互依賴的 Bean 必須為單利;

因為如果每次請求都創建一個 Bean,那么在處理循環依賴的時候,每次都會產生一個新的 Bean 實例,由于沒有全局的實例 Bean 緩存,則無法處理循環依賴

2.依賴注入的方式不能都是構造函數注入的方式。

使用構造函數注入,Bean 實例在構造函數沒有完全被調用時是不會創建的;因為 PersonA 引用 PersonB,PersonB 又引用 PersonA,兩者都無法進行初始化,產生了死鎖

3. 三級緩存原理

3.1 什么是三級緩存

Spring 是通過三級緩存的方式處理循環依賴,三級緩存是 Spring Bean 在各個階段的緩存

一級緩存(SingletonObjects):

存放已經完全實例化、初始化的bean,實現了單利bean只會實例化和初始化一次

二級緩存(EarlySingletonObjects):

存放早期暴露出來的Bean對象,bean的生命周期還未完成(未完成屬性注入與初始化的bean)

三級緩存(SingletonFactories):

三級緩存中存儲的是單利工廠緩存,通過調用該對象的 GetObject 方法,可以獲取到早期暴露出去的 Bean;在該 Bean 要被其他 Bean 引用時,Spring 就會用工廠對象創建出該 Bean 的實例對象,最終當該 Bean 完成構造的所有步驟后就會將該 Bean 放入到一級緩存中

/** 一級緩存 */
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<String, Object>(256);
/** 二級緩存 */ 
private final Map<String, Object> earlySingletonObjects = new HashMap<String, Object>(16); 
/** 三級緩存 */ 
private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<String, ObjectFactory<?>>(16);

3.2 三級緩存流程

圖片圖片

3.3 三級緩存源碼解析

創建 Bean 主要的方法是 AbstractBeanFactory.doGetBean 方法

protected <T> T doGetBean( String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly) throws BeansException {
  // 獲取bean的規范名稱
  String beanName = transformedBeanName(name); 
  Object bean;  
  // 從各級緩存中獲取bean對象 
  Object sharedInstance = getSingleton(beanName); 
  // 跟factoryBean相關判斷
  if (sharedInstance != null && args == null) { 
...
  } 
  // 獲取factorybean的真是bean
  //若為普通bean則直接返回對象

  bean = getObjectForBeanInstance(sharedInstance, name, beanName, null); 
} 
...... 
  // 創建單利bean對象 
  if (mbd.isSingleton()) { 
    sharedInstance = getSingleton(beanName, () -> { 
  try {
    // 創建bean
    return createBean(beanName, mbd, args); 
  } catch (BeansException ex) { 
    // Explicitly remove instance from singleton cache: It might have been put there 
    // eagerly by the creation process, to allow for circular reference resolution. 
    // Also remove any beans that received a temporary reference to the bean. destroySingleton(beanName); 
    throw ex; 
  } 
}); 
  bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd); 
} 
......    
// 返回bean對象 return (T) bean; }

我們看兩個比較重要獲取 Bean 的方法 GetSingleton()

// 這個方法主要是三級緩存容器,思路大概是:從一級緩存查詢,若找不到去二級緩存查詢,還是不存在則去三級緩存,若三級緩存找到了,則將bean放入二級緩存中
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
  // 從一級緩存中查找bean
  Object singletonObject = this.singletonObjects.get(beanName);
  // 判斷一級緩存查找不到bean && bean是否處于創建中,成立,則進入循環依賴
  if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
    synchronized (this.singletonObjects) {
    // 從二級緩存中查找
    singletonObject = this.earlySingletonObjects.get(beanName);
    // 二級緩存未查詢到 && 是否允許獲取早期引用
    if (singletonObject == null && allowEarlyReference) {
      // 從三級緩存查詢
      ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
      // 三級緩存存在bean
      if (singletonFactory != null) {
        // 獲取bean實例
        singletonObject = singletonFactory.getObject();
        // 從三級緩存升級到二級緩存,
        this.earlySingletonObjects.put(beanName, singletonObject);
        // 三級緩存中移除
        this.singletonFactories.remove(beanName);
        }
      }
    }
  }
   // 返回bean
  return singletonObject;
}
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {  
  Assert.notNull(beanName, "Bean name must not be null");  
  synchronized (this.singletonObjects) {        
  // 從一級緩存中獲取對應bean 
  Object singletonObject = this.singletonObjects.get(beanName);      
  // 若bean不存在 
  if (singletonObject == null) {  
    // 當前正在銷毀bean,不能創建
    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 + "'");  
    }
    // 創建前檢查,記錄正在加載狀態     
    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){  
      // 執行getObject方法創建bean
      singletonObject = this.singletonObjects.get(beanName);  
      if (singletonObject == null) {  
        throw ex;  
      }  
    } catch(BeanCreationException ex){  
      if (recordSuppressedExceptions) {  
        or (Exception suppressedException : this.suppressedExceptions) { 
          ex.addRelatedCause(suppressedException);  
      }  
    }  
      throw ex;  
    } finally{  
      if (recordSuppressedExceptions) {  
        this.suppressedExceptions = null;  
      } 
      // 單例bean創建完成后,容器移除bean
      afterSingletonCreation(beanName);  
    }  
    // newSingleton為true時,表示bean創建成功  
    // 判斷是否為新的完成整bean
    if (newSingleton) {            
      // 將bean存入一級緩存中
      addSingleton(beanName, singletonObject);  
    }  
   } 
   return singletonObject;  
  }  
}

添加與清理緩存

// 將bean放入一級緩存切清楚二級、三級緩存
protected void addSingleton(String beanName, Object singletonObject) {
  synchronized (this.singletonObjects) {xw
    // 添加到一級緩存中 
    this.singletonObjects.put(beanName, singletonObject); 
    // 從三級緩存中移除 
    this.singletonFactories.remove(beanName);
    // 從二級緩存中移除 
    this.earlySingletonObjects.remove(beanName);
    // 放入已注冊的單利池中
    this.registeredSingletons.add(beanName);
  }
}
// 添加到三級緩存
protected void addSingletonFactory(String beanName, ObjectFactory<?> singletonFactory) {
  synchronized (this.singletonObjects) {
  // 若一級緩存不存在bean實例
  if (!this.singletonObjects.containsKey(beanName)) {
    // 添加到三級緩存
    this.singletonFactories.put(beanName, singletonFactory);
    // 從第二級緩存刪除
    this.earlySingletonObjects.remove(beanName);
    // 放入已注冊的單例池里
    this.registeredSingletons.add(beanName);
  }
}

4.總結

Spring 循環依賴是通過map緩存進行處理的,其中包括一級、二級、三級緩存,作用如下:

  • 一級緩存SingletonObjects實例化、初始化實例。
  • 二級緩存EarlySingletonObjects存放的是早期的 Bean ,半成品還未初始化的 bean。
  • 三級緩存SingletonFactories是一個對象工廠,用于創建對象,然后放入到二級緩存中。同時對象如果存在 Aop 代理,那么返回的對象就是代理對象。

參考文獻

http://www.ekrvqnd.cn/article/702892.html

責任編輯:武曉燕 來源: 政采云技術
相關推薦

2023-02-26 11:15:42

緩存循環依賴

2022-12-02 12:01:30

Spring緩存生命周期

2022-03-01 18:03:06

Spring緩存循環依賴

2022-05-08 19:23:28

Spring循環依賴

2021-01-29 14:14:47

動態代理緩存

2024-03-04 08:47:17

Spring框架AOP

2025-06-26 01:55:00

2024-12-20 16:46:22

Spring三級緩存

2024-04-15 08:17:21

Spring依賴注入循環依賴

2022-01-12 07:48:19

緩存Spring 循環

2024-03-18 00:00:00

SpringBean設計

2019-11-26 14:30:20

Spring循環依賴Java

2023-10-07 08:40:57

緩存屬性Spring

2024-04-12 07:51:05

SpringBean初始化

2020-12-29 08:34:08

spring循環依賴開發

2022-08-17 07:52:31

Spring循環依賴單例池

2021-06-27 21:06:47

開發循環依賴

2020-02-06 13:40:35

編程緩存優化

2023-11-28 08:00:00

SpringJava

2020-02-10 15:50:18

Spring循環依賴Java
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 欧美一级片黄色 | 岛国在线免费观看 | 久久久久久精 | 91免费观看视频 | 青青草中文字幕 | 在线观看中文字幕 | 成人网在线观看 | 日韩在线视频一区 | 国产精品亚洲精品日韩已方 | 国产欧美精品在线 | 成人网在线 | 国产线视频精品免费观看视频 | 插插宗合网 | 日日夜夜操天天干 | 成人精品一区亚洲午夜久久久 | 91精品国产91久久综合桃花 | 国产精品久久99 | 精品少妇一区二区三区在线播放 | 亚洲精品免费观看 | 性高湖久久久久久久久 | 国产男女猛烈无遮掩视频免费网站 | 狠狠干在线 | 一区二区三区在线 | 亚洲先锋影音 | 欧美日韩黄色一级片 | 欧美色综合 | 中文字幕不卡在线88 | 91视在线国内在线播放酒店 | 国产精品123区 | 国产成人叼嘿视频在线观看 | 犬夜叉在线观看 | 日本韩国欧美在线观看 | 日本黄色影片在线观看 | 亚洲精品视频一区二区三区 | 欧美理论片在线 | 国产特级毛片aaaaaa喷潮 | eeuss国产一区二区三区四区 | av官网在线 | 成年人网站免费 | 亚洲欧美一区二区三区视频 | 性欧美xxxx |