自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

Spring如何使用三級緩存解決循環(huán)依賴

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

1. 前言

在日常開發(fā)中,Bean之間的循環(huán)依賴非常常見,Spring 已經(jīng)幫我們做到使用無感知處理,那么 Spring 是如何實現(xiàn)的呢?

2. 循環(huán)依賴簡介

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

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

圖片圖片

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

2.2 Spring 處理循環(huán)依賴的前提條件

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

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

2.依賴注入的方式不能都是構(gòu)造函數(shù)注入的方式。

使用構(gòu)造函數(shù)注入,Bean 實例在構(gòu)造函數(shù)沒有完全被調(diào)用時是不會創(chuàng)建的;因為 PersonA 引用 PersonB,PersonB 又引用 PersonA,兩者都無法進行初始化,產(chǎn)生了死鎖

3. 三級緩存原理

3.1 什么是三級緩存

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

一級緩存(SingletonObjects):

存放已經(jīng)完全實例化、初始化的bean,實現(xiàn)了單利bean只會實例化和初始化一次

二級緩存(EarlySingletonObjects):

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

三級緩存(SingletonFactories):

三級緩存中存儲的是單利工廠緩存,通過調(diào)用該對象的 GetObject 方法,可以獲取到早期暴露出去的 Bean;在該 Bean 要被其他 Bean 引用時,Spring 就會用工廠對象創(chuàng)建出該 Bean 的實例對象,最終當該 Bean 完成構(gòu)造的所有步驟后就會將該 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 三級緩存源碼解析

創(chuàng)建 Bean 主要的方法是 AbstractBeanFactory.doGetBean 方法

protected <T> T doGetBean( String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly) throws BeansException {
  // 獲取bean的規(guī)范名稱
  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); 
} 
...... 
  // 創(chuàng)建單利bean對象 
  if (mbd.isSingleton()) { 
    sharedInstance = getSingleton(beanName, () -> { 
  try {
    // 創(chuàng)建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是否處于創(chuàng)建中,成立,則進入循環(huán)依賴
  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,不能創(chuàng)建
    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 + "'");  
    }
    // 創(chuàng)建前檢查,記錄正在加載狀態(tài)     
    beforeSingletonCreation(beanName); 
    boolean newSingleton = false;
    boolean recordSuppressedExceptions = (this.suppressedExceptions == null);  
    // 如果當前沒有異常,初始化異常集合
    if (recordSuppressedExceptions) {  
      this.suppressedExceptions = new LinkedHashSet<>();  
    }  
    try {
      // 執(zhí)行匿名內(nèi)部類方法 
      singletonObject = singletonFactory.getObject(); 
      newSingleton = true; 
    }  
    catch(IllegalStateException ex){  
      // 執(zhí)行getObject方法創(chuàng)建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創(chuàng)建完成后,容器移除bean
      afterSingletonCreation(beanName);  
    }  
    // newSingleton為true時,表示bean創(chuàng)建成功  
    // 判斷是否為新的完成整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.總結(jié)

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

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

參考文獻

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

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

2023-02-26 11:15:42

緩存循環(huán)依賴

2022-12-02 12:01:30

Spring緩存生命周期

2022-03-01 18:03:06

Spring緩存循環(huán)依賴

2022-05-08 19:23:28

Spring循環(huán)依賴

2021-01-29 14:14:47

動態(tài)代理緩存

2024-03-04 08:47:17

Spring框架AOP

2024-12-20 16:46:22

Spring三級緩存

2024-04-15 08:17:21

Spring依賴注入循環(huán)依賴

2022-01-12 07:48:19

緩存Spring 循環(huán)

2019-11-26 14:30:20

Spring循環(huán)依賴Java

2023-10-07 08:40:57

緩存屬性Spring

2024-03-18 00:00:00

SpringBean設計

2024-04-12 07:51:05

SpringBean初始化

2020-12-29 08:34:08

spring循環(huán)依賴開發(fā)

2022-08-17 07:52:31

Spring循環(huán)依賴單例池

2020-02-06 13:40:35

編程緩存優(yōu)化

2021-06-27 21:06:47

開發(fā)循環(huán)依賴

2023-11-28 08:00:00

SpringJava

2020-02-10 15:50:18

Spring循環(huán)依賴Java

2020-06-22 08:07:48

Spring依賴場景
點贊
收藏

51CTO技術棧公眾號