欧洲乱码伦视频免费国产-麻豆国产精品专区-无码人妻一区二区三区精品视频-日韩免费一区二区三区超清视频-狠狠躁夜夜躁人人爽超碰97香蕉-日韩精品一区二区三区色欲av-久久人人爽av亚洲精品天堂-激情五月开心综合亚洲-久久精品无码一区二区综合好-开心五月四房播播
Spring压轴题:当循环依赖遇上Spring AOP-南宫28

Spring压轴题:当循环依赖遇上Spring AOP

2026-01-16 23:54:27投稿人:云開(大連)有限公司圍觀4443663 評論

Spring壓軸題 :當循環(huán)依賴遇上Spring AOP

前言

:Spring如何解決循環(huán)依賴  ?

 :Spring通過提前曝光機制 ,利用三級緩存解決循環(huán)依賴(這原理還是挺簡單的  ,參考:三級緩存 、圖解循環(huán)依賴原理)

再問:Spring通過提前曝光 ,直接曝光到二級緩存已經可以解決循環(huán)依賴問題了,為什么一定要三級緩存 ?

再細問 :如果循環(huán)依賴的時候  ,所有類又都需要Spring AOP自動代理,那Spring如何提前曝光?曝光的是原始bean還是代理后的bean ?

這些問題算是Spring源碼的壓軸題了,如果這些問題都弄明白,恭喜你順利結業(yè)Spring源碼了 。就單單對Spring這一塊的理解,不夸張的說可以達到阿里水準了

源碼分析

進入正題,在Spring創(chuàng)建Bean的核心代碼doGetBean中 ,在實例化bean之前 ,會先嘗試從三級緩存獲取bean,這也是Spring解決循環(huán)依賴的開始

(一) 緩存中獲取bean

// AbstractBeanFactory.javaprotected T doGetBean(final String name, @Nullable final ClassrequiredType,   @Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {   final String beanName = transformedBeanName(name);  Object bean;  // 2. 嘗試從緩存中獲取bean  Object sharedInstance = getSingleton(beanName);  ...}

protected Object getSingleton(String beanName, boolean allowEarlyReference) {   // 從一級緩存獲取	,key=beanName value=bean  Object singletonObject = this.singletonObjects.get(beanName);  if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {    synchronized (this.singletonObjects) {     // 從二級緩存獲取,key=beanName value=bean    singletonObject = this.earlySingletonObjects.get(beanName);    // 是否允許循環(huán)引用    if (singletonObject == null && allowEarlyReference) {      /**      * 三級緩存獲取,key=beanName value=objectFactory
,objectFactory中存儲getObject()方法用于獲取提前曝光的實例      *      * 而為什么不直接將實例緩存到二級緩存,而要多此一舉將實例先封裝到objectFactory中?      * 主要關鍵點在getObject()方法并非直接返回實例,而是對實例又使用      * SmartInstantiationAwareBeanPostProcessor的getEarlyBeanReference方法對bean進行處理      *      * 也就是說
,當spring中存在該后置處理器,所有的單例bean在實例化后都會被進行提前曝光到三級緩存中	,      * 但是并不是所有的bean都存在循環(huán)依賴
,也就是三級緩存到二級緩存的步驟不一定都會被執(zhí)行,有可能曝光后直接創(chuàng)建完成
,沒被提前引用過
,      * 就直接被加入到一級緩存中。因此可以確保只有提前曝光且被引用的bean才會進行該后置處理       */     ObjectFactory<?>singletonFactory = this.singletonFactories.get(beanName);     if (singletonFactory != null) {       /**       * 通過getObject()方法獲取bean,通過此方法獲取到的實例不單單是提前曝光出來的實例,       * 它還經過了SmartInstantiationAwareBeanPostProcessor的getEarlyBeanReference方法處理過
。       * 這也正是三級緩存存在的意義
,可以通過重寫該后置處理器對提前曝光的實例,在被提前引用時進行一些操作        */      singletonObject = singletonFactory.getObject();      // 將三級緩存生產的bean放入二級緩存中      this.earlySingletonObjects.put(beanName, singletonObject);      // 刪除三級緩存      this.singletonFactories.remove(beanName);     }    }   }  }  return singletonObject; }

三級緩存分別是 :