中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Spring解決循環依賴問題及三級緩存的作用是什么

發布時間:2022-07-12 14:35:38 來源:億速云 閱讀:163 作者:iii 欄目:開發技術

本文小編為大家詳細介紹“Spring解決循環依賴問題及三級緩存的作用是什么”,內容詳細,步驟清晰,細節處理妥當,希望這篇“Spring解決循環依賴問題及三級緩存的作用是什么”文章能幫助大家解決疑惑,下面跟著小編的思路慢慢深入,一起來學習新知識吧。

前言

所謂的三級緩存只是三個可以當作是全局變量的Map,Spring的源碼中大量使用了這種先將數據放入容器中等使用結束再銷毀的代碼風格

Spring解決循環依賴問題及三級緩存的作用是什么

Spring的初始化過程大致有四步:

  • 創建beanFactory,加載配置文件

  • 解析配置文件轉化beanDefination,獲取到bean的所有屬性、依賴及初始化用到的各類處理器等

  • 刷新beanFactory容器,初始化所有單例bean

  • 注冊所有的單例bean并返回可用的容器

我們說的循環依賴就是第四步在給Bean屬性注入的時候發生的一個問題

1什么是循環依賴

循環依賴就是:

假設有兩個類 A和B,A中需要注入B,B中需要注入A
由于A注入B時B沒有創建,B創建時A也無法創建導致的死循環問題

Spring解決循環依賴問題及三級緩存的作用是什么

2 如何解決循環依賴

我們都知道AOP是Spring的一個重要核心思想,其實現就是根據動態代理來實現的,也就是說我們的Bean其實很大概率都是要生成代理類,讓我們先來看無代理的情況:

Bean的初始化大概是這樣的:

Spring解決循環依賴問題及三級緩存的作用是什么

根據以上步驟可以看出bean初始化是一個相當復雜的過程,假如初始化A bean時,發現A bean依賴B bean,即A初始化執行到了第4步填充屬性,需要注入B bean,此時B還沒有初始化,則需要暫停A,先去初始化B,那么此時new出來的A對象放哪里,直接放在容器Map里顯然不合適,半殘品怎么能用,所以需要提供一個可以標記創建中bean(A)的Map,可以提前暴露正在創建的bean供其他bean依賴,而如果初始化A所依賴的bean B時,發現B也需要注入一個A的依賴(即發生循環依賴),則B可以從創建中的beanMap中直接獲取A對象(創建中)注入A,然后完成B的初始化,返回給正在注入屬性的A,最終A也完成初始化,皆大歡喜。

如果沒有循環依賴,A 依賴B,就是創建B,B依賴C就去創建C,創建完了逐級返回就行,并不需要什么緩存,所以,一級緩存之后的其他緩存(二三級緩存)就是為了解決循環依賴而設立的
一級緩存其實就是我們的成熟的Bean了,可以直接被使用

我們去看一下源碼:

Spring解決循環依賴問題及三級緩存的作用是什么

Spring解決循環依賴問題及三級緩存的作用是什么

Spring解決循環依賴問題及三級緩存的作用是什么

從源碼中我們可以看到,三級緩存里放的并不是實例化的Bean,而是一個工廠,這是為什么呢?
循環依賴在實際應用可能會有,但很少,簡單的應用場景是: controller注入service,service注入mapper,只有復雜的業務,可能service互相引用,有可能出現循環依賴,所以為了出現循環依賴才去解決,不出現就不解決,雖然支持循環依賴,但是只有在出現循環依賴時才真正暴露早期對象,否則只暴露個獲取bean的方法,并沒有真正暴露bean,因為這個方法不會被執行到,這塊的實現就是三級緩存(singletonFactories),只緩存了一個單例bean工廠
為什么是一個工廠?或者說這個工廠的作用?
三級緩存bean工廠的getObject方式,實際執行的是getEarlyBeanReference,如果對象需要被代理(存在beanPostProcessors -> SmartInstantiationAwareBeanPostProcessor),則提前生成代理對象。

Spring解決循環依賴問題及三級緩存的作用是什么

三級緩存已經解決所有問題了,二級緩存用來做什么呢?為什么三級緩存不直接叫做二級緩存?這個應該是在緩存使用時決定的:

Spring解決循環依賴問題及三級緩存的作用是什么

此時這個方法中的判斷邏輯是:

  • 一級緩存中沒有

  • 對象A確實正在創建中

  • 二級緩存中也沒有

  • 最終去三級緩存中獲取對象,從三級緩存獲取后把對象從三級緩存刪除然后放入到二級緩存中,由于當初放入到三級緩存中的是一個工廠,所以從三級緩存中拿對象是調用getEarlyBeanReference這個方法獲取,這個方法的作用是如果對象需要代理,那么就返回代理類,如果不需要代理就返回原生類,至此屬性注入A完成

那么為什么要把對象從三級緩存放到二級緩存呢?

給大家一個循環依賴的流程圖,大家一看便知:

Spring解決循環依賴問題及三級緩存的作用是什么

看到了嗎,如果AB都需要代理,我們在A的屬性注入時創建了B,但是此時A還是原生的A,但是我們需要代理A,而代理A在B注入A時已經創建并放入二級緩存中了,我們直接從二級緩存拿然后替換原生A即可。

所以,我理解的是二級緩存是為了應對代理這個情況而生的
至此,循環依賴的問題已經完美解決

3無法解決的循環依賴

構造函數循環依賴:

如果我們的成員屬性是在構造函數里呢?
首先要解決循環依賴就是要先實例化然后放入三級緩存暴露出來,那么如果是構造函數這一步循環依賴,
實例化的時候就會產生無限遞歸創建,所以不能解決

多例的循環依賴:

如果是多例的,在容器初始化的時候,不會去創建,所以早期沒有放入到三級緩存中暴露出來,所以無法解決循環依賴,會報錯。

讀到這里,這篇“Spring解決循環依賴問題及三級緩存的作用是什么”文章已經介紹完畢,想要掌握這篇文章的知識點還需要大家自己動手實踐使用過才能領會,如果想了解更多相關內容的文章,歡迎關注億速云行業資訊頻道。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

广饶县| 澄城县| 包头市| 科尔| 西丰县| 宝丰县| 金川县| 肇源县| 黑河市| 七台河市| 赣榆县| 靖宇县| 临潭县| 前郭尔| 剑阁县| 盱眙县| 河津市| 旬邑县| 如东县| 拉萨市| 鄂托克前旗| 玉树县| 建宁县| 连山| 新巴尔虎左旗| 吉林省| 洪湖市| 富顺县| 托里县| 淮安市| 虹口区| 石台县| 渑池县| 乌什县| 南涧| 玉屏| 米脂县| 新邵县| 通城县| 和龙市| 锡林郭勒盟|