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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

初始化bean(二)—— 缓存部分

發(fā)布時間:2025/3/8 编程问答 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 初始化bean(二)—— 缓存部分 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

上一篇博客,講了下spring如何初始化bean的 當然,當時只討論了很簡單的一種情況:初次加載bean時候,并且只考慮了單例。

這篇博客會試著理清楚spring在加載bean的時候的一部分緩存。關于解決循環(huán)引用所使用的緩存,可以看這篇博客

從doGetBean開始

首先再次回到doGetBean方法

上一篇博客里,我對doGetBean進行了簡化,省略了很多多例及第二次加載相關的代碼。

現在想下,如果讓我們業(yè)務上使用緩存會怎么做。
1)先從緩存查下有沒有所需數據
2)沒有的話從db加載
3)加載后存到緩存里

緩存的用法無非是這樣。spring也是這樣使用的。

getSingleton方法

現在再來回顧getSingleton方法就很清楚了

這里我會把流程再簡化下,去掉那些擴展的,異常處理等

public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {Assert.notNull(beanName, "'beanName' must not be null");synchronized (this.singletonObjects) {//先試著從緩存中加載Object singletonObject = this.singletonObjects.get(beanName);if (singletonObject == null) {//異常檢查 ... //...beforeSingletonCreation(beanName);boolean newSingleton = false;//異常記錄...try {//調用ObjectFactory的getObject生成這個對象singletonObject = singletonFactory.getObject();newSingleton = true;}// 省略了異常處理finally{//....afterSingletonCreation(beanName);}if (newSingleton) {//添加到緩存里addSingleton(beanName, singletonObject);}}return (singletonObject != NULL_OBJECT ? singletonObject : null);} }

這樣看就非常清楚了
1)從singleObjects試著找下對應的對象
2)從singletonFactory里創(chuàng)建對象
3)添加到緩存中

和我們平常使用緩存的方式沒有任何不同

addSingleton記錄緩存

看doGetBean方法,讓我感到很暈的地方就是,各種各樣緩存。(好多hashMap)而addSingleton方法就是操作緩存的一部分入口。

protected void addSingleton(String beanName, Object singletonObject) {synchronized (this.singletonObjects) {this.singletonObjects.put(beanName, (singletonObject != null ? singletonObject : NULL_OBJECT));this.singletonFactories.remove(beanName);this.earlySingletonObjects.remove(beanName);this.registeredSingletons.add(beanName);} }

這里我們先挑看得懂的來分析。

Map<String, Object> singletonObjects 存放了 beanName -> 創(chuàng)建出來的對象
Set<String> registeredSingletons 存放了已注冊的單例對象

好像就這兩個看得懂哦(~ ̄▽ ̄)~ 沒事我們繼續(xù)分析下去

回到doGetBean開頭

protected <T> T doGetBean(final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly)throws BeansException {final String beanName = transformedBeanName(name);Object bean;Object sharedInstance = getSingleton(beanName);//..... }

doGetBean一開始就試圖通過getSingleton方法獲取對應的bean
我們再回頭看下getSinglteton方法

protected Object getSingleton(String beanName, boolean allowEarlyReference) {//已創(chuàng)建的對象里面找下Object singletonObject = this.singletonObjects.get(beanName);//沒找到,并且當前類正在被創(chuàng)建if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {synchronized (this.singletonObjects) {singletonObject = this.earlySingletonObjects.get(beanName);if (singletonObject == null && allowEarlyReference) {ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);if (singletonFactory != null) {singletonObject = singletonFactory.getObject();this.earlySingletonObjects.put(beanName, singletonObject);this.singletonFactories.remove(beanName);}}}}return (singletonObject != NULL_OBJECT ? singletonObject : null); }

第一行很熟悉,從已加載的對象的緩存里找下。
第二行判斷,從方法名很容易猜到意思。只有當從緩存里找不到,并且當前類正在被創(chuàng)建才會走到里面的邏輯。

看下isSingletonCurrentlyInCreation方法

public boolean isSingletonCurrentlyInCreation(String beanName) {return this.singletonsCurrentlyInCreation.contains(beanName); }

這里又出現了一個不認識的緩存 = =

Set<String> singletonsCurrentlyInCreation

從變量名,很容易猜到是記錄當前單例是否正在被創(chuàng)建。

我們跟下往這個set里添加 值的地方。插入值的地方就在getSingleton里的beforeSingletonCreation 這一步里。
之前分析getSingleton方法時,我關注的是如何創(chuàng)建bean,如何使用singletonObjects緩存的。
其實在創(chuàng)建bean前,與創(chuàng)建bean后,有兩個方法用于做些前置以及后置處理。分別是beforeSingletonCreation 與 afterSingletonCreation方法。

我們看下這兩個方法里都做了啥

創(chuàng)建bean的前置與后置處理

protected void beforeSingletonCreation(String beanName) {if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.add(beanName)) {throw new BeanCurrentlyInCreationException(beanName);} }protected void afterSingletonCreation(String beanName) {if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.remove(beanName)) {throw new IllegalStateException("Singleton '" + beanName + "' isn't currently in creation");} }

這里又出現了兩個緩存 inCreationCheckExclusions 和 singletonsCurrentlyInCreation

inCreationCheckExclusions這個我們先不管,到了這里singletonsCurrentlyInCreation就很清楚了,spring會在創(chuàng)建一個單例對象之前,記錄到singletonsCurrentlyInCreation里,在創(chuàng)建完后,從singletonsCurrentlyInCreation里刪除。

Set<String> singletonsCurrentlyInCreation 當前正在創(chuàng)建的beanName

回到getSingleton方法

if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {

到了這里我有幾個問題:
1)為啥getSingleton方法里要進行這樣的判斷?
2)一般來說我們使用spring時候,都是單線程的。那么按照這個代碼,創(chuàng)建之前添加進去,添加之后刪除。那么豈不是永遠不會走到這個if條件里?這些問題先記著,等分析依賴注入時候再回過頭來解決。

總結

到了這里,還是有很多不知道有什么用的緩存。這些緩存會在研究依賴注入以及循環(huán)引用時候繼續(xù)分析。

總結

以上是生活随笔為你收集整理的初始化bean(二)—— 缓存部分的全部內容,希望文章能夠幫你解決所遇到的問題。

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