日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 综合教程 >内容正文

综合教程

spring 如何检测到循环依赖/如何解决循环依赖

發布時間:2023/12/15 综合教程 26 生活家
生活随笔 收集整理的這篇文章主要介紹了 spring 如何检测到循环依赖/如何解决循环依赖 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

spring針對循環依賴問題 不能完全解決 對于不能解決的只能檢測到并拋出異常

1. spring針對構造器方法的 單實例對象和原型對象是無法解決循環依賴問題的

先說結論,

  針對單例對象 getSingleton方法中 有個beforeSingletonCreation 方法 這個方法是用來檢測循環依賴的

  原型對象isPrototypeCurrentlyInCreation方法beforePrototypeCreation方法配合檢測循環依賴

  注:inCreationCheckExclusions和singletonsCurrentlyInCreation 是兩個set

1 protected void beforeSingletonCreation(String beanName) {
2         if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.add(beanName)) {
3             throw new BeanCurrentlyInCreationException(beanName);
4         }
5     }

  以AB兩個單例對象舉例,

  

1 Class A(){
2     A(B b){
3   }  
4 }
5 
6 Class B(){
7     B(A a){
8   }  
9 }

  對象A在實例化的時候(getBean方法),會先執行beforeSingletonCreation方法 吧自己的beanName放入set中,然后去執行實例化 解析構造器方法的時候發現 需要用到對象B ,所以去getBean(B)

  B對象在一級緩存是沒有的(因為是還未實例化),所以去創建單例B,會執行和A一樣的操作,把自己的beanName放入set中,然后解析構造器的時候發現依賴A對象,去一級緩存獲取是沒有的(因為A對象實例化還未完成 未放入到一級緩存中)

  所以去實例化A 放入set的時候 發現已經存在及會拋出異常

1 protected boolean isPrototypeCurrentlyInCreation(String beanName) {
2         Object curVal = this.prototypesCurrentlyInCreation.get();
3         return (curVal != null &&
4                 (curVal.equals(beanName) || (curVal instanceof Set && ((Set<?>) curVal).contains(beanName))));
5     }
 1 protected void beforePrototypeCreation(String beanName) {
 2         Object curVal = this.prototypesCurrentlyInCreation.get();
 3         if (curVal == null) {
 4             this.prototypesCurrentlyInCreation.set(beanName);
 5         }
 6         else if (curVal instanceof String) {
 7             Set<String> beanNameSet = new HashSet<>(2);
 8             beanNameSet.add((String) curVal);
 9             beanNameSet.add(beanName);
10             this.prototypesCurrentlyInCreation.set(beanNameSet);
11         }
12         else {
13             Set<String> beanNameSet = (Set<String>) curVal;
14             beanNameSet.add(beanName);
15         }
16     }

對象在實例化之前會先調用isPrototypeCurrentlyInCreation方法,如果set中沒有繼續執行,實例化的時候調用beforePrototypeCreation方法 放入set中,在之后的循環依賴中 查詢到set中有自己的beanName 則拋出異常

那么spring對set方法注入 是如何解決循環依賴問題的呢,一樣先說結論 是使用第三級緩存來解決的

1. 在實例化bean A的時候 先去查看一級緩存中是否有(執行的方法getSingleton)

并且會查詢currentlyCreationSet中有沒有

2. 處理一下depend-on依賴 或者檢查一下是否是抽象等等安全性校驗

3.把單實例的A 的beanName放入currentlyCreationSet中

4. 實例化A對象因為是set注入 所以這時使用的空參構造 去反射出實例對象 得到一個早期對象(未進行屬性注入的對象,未執行init方法調用,未進行后處理器處理,早期對象和處理后的對象的內存地址是一樣的aop對象除外)

5. 早期實例A封裝到objectFactory對象中,放入三級緩存

6. 進行依賴注入 依賴注入的時候發現依賴Bean B 再去執行getBean方法 重復執行1-6步 拿到一個B的早期對象objectFactory 放入到三級緩存

7. 處理B的依賴注入 發現B依賴了A 執行getbean方法 從1開始執行 去一級緩存查詢沒有 去currentlyCreationSet查詢有A 去三級緩存中拿到A的早期實例 放入二級緩存清除三級緩存中的A早期實例并返回這個早期實例 B繼續執行完成了B對象的實例 放入一級緩存中 清除掉二三級緩存相關數據

8. 繼續執行A的實例化步驟 A完成實例化 存入一級緩存 清除二三級緩存相關數據

 1 protected Object getSingleton(String beanName, boolean allowEarlyReference) {
 2         Object singletonObject = this.singletonObjects.get(beanName);
 3         if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
 4             synchronized (this.singletonObjects) {
 5                 singletonObject = this.earlySingletonObjects.get(beanName);
 6                 if (singletonObject == null && allowEarlyReference) {
 7                     ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
 8                     if (singletonFactory != null) {
 9                         singletonObject = singletonFactory.getObject();
10                         this.earlySingletonObjects.put(beanName, singletonObject);
11                         this.singletonFactories.remove(beanName);
12                     }
13                 }
14             }
15         }
16         return singletonObject;
17     }

總結

以上是生活随笔為你收集整理的spring 如何检测到循环依赖/如何解决循环依赖的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。