国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

Spring FrameWork從入門(mén)到NB -三級(jí)緩存解決循環(huán)依賴(lài)內(nèi)幕 (一)

這篇具有很好參考價(jià)值的文章主要介紹了Spring FrameWork從入門(mén)到NB -三級(jí)緩存解決循環(huán)依賴(lài)內(nèi)幕 (一)。希望對(duì)大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請(qǐng)大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問(wèn)。

循環(huán)依賴(lài)就是我依賴(lài)你、你依賴(lài)我,或者A依賴(lài)B、B依賴(lài)C、C依賴(lài)A…組成的錯(cuò)綜復(fù)雜的依賴(lài)關(guān)系。

其實(shí)各種不同的依賴(lài)關(guān)系最終從邏輯上都可以演變?yōu)椋何乙蕾?lài)你、你依賴(lài)我。

循環(huán)依賴(lài)大致可以分為兩種情況:

  1. 屬性依賴(lài):比如A對(duì)象有一個(gè)屬性B,B對(duì)象有屬性A。
  2. 構(gòu)造器依賴(lài):A對(duì)象的構(gòu)造器中有參數(shù)B,B對(duì)象的構(gòu)造器有參數(shù)A。

構(gòu)造器依賴(lài)是Spring解決不了的(指的是A、B不存在其他構(gòu)造器,或者Spring需要通過(guò)互相依賴(lài)的構(gòu)造器創(chuàng)建A、B對(duì)象),這種死結(jié)你自己寫(xiě)代碼都沒(méi)辦法解決,Spring當(dāng)然也沒(méi)有辦法。

Spring通過(guò)其特有的三級(jí)緩存機(jī)制能解決屬性依賴(lài)。順便說(shuō)一下,其實(shí)Spring官網(wǎng)或相關(guān)資料中并沒(méi)有提出過(guò)三級(jí)緩存的說(shuō)法,也不太清楚這種說(shuō)法從哪兒來(lái)(或者是我疏漏了沒(méi)有查到),反正很NB、很高深的樣子,其實(shí)如果你認(rèn)真讀源碼,換做一種真實(shí)的說(shuō)法:Spring最終通過(guò)三個(gè)Map的巧妙使用解決循環(huán)依賴(lài)問(wèn)題…也就沒(méi)有那么NB、那么高深、尤其是沒(méi)有那么高大上了。但是不管怎么說(shuō),Spring解決循環(huán)依賴(lài)的框架還是值得我們認(rèn)真學(xué)習(xí)掌握的。因?yàn)镾pring各路大牛的設(shè)計(jì)思想確實(shí)#@¥%……%*(確實(shí)和你的收入會(huì)直接相關(guān)所以你一定有必要花點(diǎn)時(shí)間精力徹底搞清楚)。

三級(jí)緩存框架

先上一張圖,對(duì)三級(jí)緩存有個(gè)直觀印象:
Spring FrameWork從入門(mén)到NB -三級(jí)緩存解決循環(huán)依賴(lài)內(nèi)幕 (一)

抱歉,畫(huà)的有點(diǎn)low,不過(guò)還是能說(shuō)明問(wèn)題的哈。

Spring IoC容器中當(dāng)然不止是DefaultSingletonBeanRegistry一個(gè)容器,但三級(jí)緩存就是針對(duì)單例Bena來(lái)說(shuō)的,其實(shí)如果只是從Bean容器的角度來(lái)講,Spring IoC容器很大程度上講的也就是單例Bean的容器,原型Bean本來(lái)也是每次使用、每次創(chuàng)建,所以也就不需要緩存。只有單例Bean在Spring IoC容器中是一次創(chuàng)建長(zhǎng)期駐留,駐留的地方就是三級(jí)緩存中的“一級(jí)緩存”。

如上圖,三級(jí)緩存定義在DefaultSingletonBeanRegistry中:

  1. 三級(jí)緩存:存儲(chǔ)bean name和bean工廠的容器。
  2. 二級(jí)緩存:存儲(chǔ)bean name和bean實(shí)例,二級(jí)緩存中的bean實(shí)例剛剛完成實(shí)例化、尚未完成屬性賦值,所以是半成品。
  3. 一級(jí)緩存:存儲(chǔ)最終完成創(chuàng)建的Bean,應(yīng)用getBean或者自動(dòng)裝配的Bean就是從以及緩存獲取的。
Spring解決循環(huán)依賴(lài)的詳細(xì)過(guò)程

其實(shí)認(rèn)真讀源碼,研究完Spring的Bean創(chuàng)建過(guò)程之后,循環(huán)依賴(lài)的原理就一目了然了(雖然很復(fù)雜)。

Spring的Bean創(chuàng)建過(guò)程相對(duì)來(lái)說(shuō)還是比較復(fù)雜的,研究清楚全貌還是要花費(fèi)點(diǎn)時(shí)間的,我們的策略就是一步一步抽絲剝繭以及各個(gè)擊破,今天的主要目標(biāo)就是三級(jí)緩存解決循環(huán)依賴(lài)的過(guò)程,所以對(duì)其他過(guò)程就要忽略。

Spring源碼,Bean的創(chuàng)建過(guò)程:

AbstractBeanFactory#getBean

創(chuàng)建和獲取bean的統(tǒng)一入口,會(huì)調(diào)用doGetBean方法。

AbstractBeanFactory#doGetBean
  1. 首先調(diào)用DefaultSingletonBeanRegistry#getSingleton(beanName,true)方法,注意這個(gè)getSingleton方法是不會(huì)創(chuàng)建bean的。
  2. 如果沒(méi)有拿到Bean,就準(zhǔn)備創(chuàng)建Bean
  3. 首先檢查是否有Dependon,有的話(huà),先創(chuàng)建Dependon
  4. 如果要?jiǎng)?chuàng)建的是單例bean,則調(diào)用getSingleton(beanName,factory)創(chuàng)建bean,注意這個(gè)才會(huì)創(chuàng)建bean
  5. 否則,如果是原型bean…和今天的話(huà)題無(wú)關(guān),暫時(shí)忽略
DefaultSingletonBeanRegistry#getSingleton(beanName,boolean)

我們上面說(shuō)過(guò)了,這里不會(huì)創(chuàng)建bean:

  1. 一級(jí)緩存存在,則直接返回
  2. 一級(jí)緩存不存在并且Bean正在創(chuàng)建中,從二級(jí)緩存獲取
  3. 二級(jí)緩存獲取到則返回,否則檢查三級(jí)緩存
  4. 三級(jí)緩存有的話(huà),調(diào)用三級(jí)緩存的bean工廠加工bean,放入二級(jí)緩存后,返回,并清除三級(jí)緩存
  5. 否則三級(jí)緩存沒(méi)有的話(huà)返回null
DefaultSingletonBeanRegistry#getSingleton(beanName,F(xiàn)actory)

這個(gè)getSingleton擔(dān)負(fù)著創(chuàng)建bean實(shí)例的任務(wù),如果獲取不到的話(huà),會(huì)創(chuàng)建:

  1. 一級(jí)緩存存在,則直接返回
  2. 否則,當(dāng)前bean放入“正在創(chuàng)建中”列表(singletonsCurrentlyInCreation)
  3. 使用Factory創(chuàng)建Bean實(shí)例:調(diào)用AbstractAutowireCapableBeanFactory#createBean方法
  4. 當(dāng)前bean從“正在創(chuàng)建中”列表移出
  5. 完成創(chuàng)建的Bean從二級(jí)、三級(jí)緩存移出,放入一級(jí)緩存

我們需要注意的是,這個(gè)方法調(diào)用完成之后,一個(gè)完整的bean就被創(chuàng)建出來(lái)、被放入到一級(jí)緩存了。

但你要知道的是,這個(gè)方法不會(huì)那么容易完成的,玄機(jī)就在createBean方法中,如果有依賴(lài)的話(huà)還會(huì)遞歸調(diào)用AbstractBeanFactory#getBean方法的,邏輯又繞回去了…

AbstractAutowireCapableBeanFactory#createBean

真正創(chuàng)建Bean的地方:

  1. 創(chuàng)建Bean實(shí)例(原始類(lèi)的實(shí)例,或者CGLIB代理對(duì)象實(shí)例)
  2. 如果是單例Bean并且當(dāng)前Bean正在創(chuàng)建中,則調(diào)用addSingletonFactory:作用是創(chuàng)建一個(gè)工廠方法,添加到三級(jí)緩存。
  3. 調(diào)用populateBean方法,屬性填充(可能會(huì)發(fā)生循環(huán)依賴(lài)啊…)

需要特別注意的是,三級(jí)緩存就是在這兒創(chuàng)建的,存儲(chǔ)的內(nèi)容是一個(gè)bean factory、使用lamda表達(dá)式創(chuàng)建,工廠方法是getEarlyBeanReference。

getEarlyBeanReference方法后面從三級(jí)緩存獲取對(duì)象的時(shí)候會(huì)回調(diào),作用是通過(guò)SmartInstantiationAwareBeanPostProcessor的getEarlyBeanReference方法最終調(diào)用到wrapIfNecessary方法,目的是判斷bean如果需要AOP的話(huà)則生成他的代理對(duì)象。

三級(jí)緩存存儲(chǔ)bean factory、而不是存儲(chǔ)bean實(shí)例的目的就是為了解決依賴(lài)注入過(guò)程中的代理對(duì)象的處理的。

這部分內(nèi)容確實(shí)有點(diǎn)繞,是需要?jiǎng)觿?dòng)腦子認(rèn)真仔細(xì)思考一下才能搞明白的。

AbstractAutowireCapableBeanFactory#populateBean

屬性填充,這個(gè)過(guò)程中處理自動(dòng)封裝,會(huì)有依賴(lài)注入。

調(diào)用AutowiredAnnotationBeanPostProcessor#postProcessProperties方法。

然后,AutowiredAnnotationBeanPostProcessor#postProcessProperties進(jìn)行屬性賦值。

然后,再調(diào)用DefaultListableBeanFactory#resolveFieldValue方法。

最后,老套路,DefaultListableBeanFactory#doResolveDependency方法。

方法doResolveDependency中首先解決候選注入對(duì)象的問(wèn)題,這部分代碼中包含依賴(lài)注入是查找對(duì)象(DL)的真相,這部分不是今天的主題,跳過(guò)。

DL查找到的肯定不是待注入的對(duì)象,而是待注入對(duì)象的beanName。

那猜想一下,拿到待注入的beanName之后,一定是要拿到bean對(duì)象之后再注入的,Spring會(huì)怎么處理呢?怎么根據(jù)beanName拿到bean對(duì)象呢?

其實(shí)不難猜到!

doResolveDependency方法會(huì)調(diào)用DependencyDescriptor#resolveCandidate方法,resolveCandidate方法調(diào)用beanFactory.getBean獲取對(duì)象,其實(shí)最終調(diào)用的是AbstractBeanFactory的getBean方法。

揉一揉昏花的老眼,是否感覺(jué)到似曾相識(shí)呢?

沒(méi)錯(cuò),往上翻,就是我們開(kāi)始分析循環(huán)依賴(lài)的入口處,又轉(zhuǎn)回去了。

所以沒(méi)錯(cuò),Spring IoC在Bean實(shí)例化、依賴(lài)注入的過(guò)程,就是一個(gè)不斷遞歸調(diào)用的過(guò)程。

小結(jié)

以上,就是Spring IoC的bean的實(shí)例化以及依賴(lài)注入、三級(jí)緩存解決循環(huán)依賴(lài)的主要邏輯了,整理一下、用幾個(gè)例子推導(dǎo)一下,相信就能搞清楚這部分內(nèi)容了。

你如果不相信的話(huà)我們下一篇文章就來(lái)推導(dǎo)一下。

上一篇 Spring FrameWork從入門(mén)到NB -classpath掃描和組件托管文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-500531.html

到了這里,關(guān)于Spring FrameWork從入門(mén)到NB -三級(jí)緩存解決循環(huán)依賴(lài)內(nèi)幕 (一)的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來(lái)自互聯(lián)網(wǎng)用戶(hù)投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場(chǎng)。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請(qǐng)注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請(qǐng)點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • spring 的循環(huán)依賴(lài)以及spring為什么要用三級(jí)緩存解決循環(huán)依賴(lài)

    spring 的循環(huán)依賴(lài)以及spring為什么要用三級(jí)緩存解決循環(huán)依賴(lài)

    ??????? bean的生命周期 ??????? 這里簡(jiǎn)單過(guò)一下 class -無(wú)參構(gòu)造 -普通對(duì)象 -依賴(lài)注入(對(duì)加了autowire等的屬性賦值) -初始化前-初始化 -初始化后(aop) -放入單例池的map(一級(jí)緩存) -bean對(duì)象 這里提一點(diǎn)單例bean單例bean 其實(shí)就是用mapbeanName,Bean對(duì)象創(chuàng)建的,多例bean就不

    2024年02月15日
    瀏覽(24)
  • Spring使用三級(jí)緩存解決循環(huán)依賴(lài)?終于完全弄明白了

    文章閱讀前推薦 推薦先去看看源碼,源碼很短,但是對(duì)于我們?cè)谀X子里構(gòu)建一個(gè)完整思路很重要??雌饋?lái)非常簡(jiǎn)單,只需要雙擊shift,全局查找文件:AbstractAutowireCapableBeanFactory,找到550行左右的doCreateBean方法,重點(diǎn)看一下580行到600行這20行代碼就行,包含了三級(jí)緩存、屬性注

    2024年03月25日
    瀏覽(31)
  • Spring 為什么要用三級(jí)緩存來(lái)解決循環(huán)依賴(lài)(AOP),二級(jí)緩存不行嗎

    解決有代理對(duì)象的循環(huán)依賴(lài)不一定要三級(jí)緩存,用二級(jí)甚至一級(jí)也能解決,下面討論下Spring為什么選擇三級(jí)緩存這個(gè)方案。 Spring最開(kāi)始是沒(méi)有三級(jí)緩存的,后面版本因?yàn)橐肓薃OP,有了代理對(duì)象,又因?yàn)榇嬖谘h(huán)依賴(lài),為了保證依賴(lài)注入過(guò)程注入的是代理對(duì)象,且不完全打破

    2024年04月26日
    瀏覽(23)
  • SpringBoot 三級(jí)緩存解決循環(huán)依賴(lài)源碼分析

    SpringBoot 三級(jí)緩存解決循環(huán)依賴(lài)源碼分析

    在 SpringBoot 框架中,如果只存在兩級(jí)緩存,那么當(dāng)發(fā)生循環(huán)依賴(lài)的時(shí)候可能存在異常的對(duì)象創(chuàng)建流程如下圖所示: 創(chuàng)建 A 的空白對(duì)象 a1 解析填充 A 對(duì)象的屬性,發(fā)現(xiàn)依賴(lài)的 B 對(duì)象未創(chuàng)建,則觸發(fā) B 對(duì)象創(chuàng)建 創(chuàng)建 B 對(duì)象過(guò)程中,填充對(duì)象屬性時(shí)發(fā)現(xiàn)依賴(lài) A 對(duì)象,此時(shí)從緩存中

    2024年02月11日
    瀏覽(21)
  • springIoc依賴(lài)注入循環(huán)依賴(lài)三級(jí)緩存

    springIoc依賴(lài)注入循環(huán)依賴(lài)三級(jí)緩存

    理論思想,原來(lái)的對(duì)象是由使用者來(lái)進(jìn)行控制,有了spring之后,可以把整個(gè)對(duì)象交給spring來(lái)幫我們進(jìn)行管理 依賴(lài)注入,把對(duì)應(yīng)的屬性的值注入到具體的對(duì)象中,@autowired,populateBean完成屬性的注入 beanFactory,存儲(chǔ)對(duì)象,使用map結(jié)構(gòu)來(lái)存儲(chǔ),在spring中一般存在三級(jí)緩存,singleton

    2024年01月16日
    瀏覽(20)
  • Spring FrameWork從入門(mén)到NB - BeanPostProcessor

    Spring框架之所以NB,BeanPostProcessor功不可沒(méi)。BeanPostProcessor通過(guò)生命周期回調(diào)實(shí)現(xiàn)對(duì)Bean的增強(qiáng)比如,其實(shí)Spring的AOP功能主要就是通過(guò)BeanPostProcessor實(shí)現(xiàn)的,以及,Spring重要的自動(dòng)裝配功能,也是通過(guò)BeanPostProcessor實(shí)現(xiàn)的。 BeanPostProcessor生效原理 BeanPostProcessor指的是Spring容器中所

    2024年02月12日
    瀏覽(20)
  • Spring FrameWork從入門(mén)到NB - Spring AOP - 概念

    什么是AOP AOP - Aspect Oriented Programming的縮寫(xiě),面向切面編程。 面向切面編程AOP是面向?qū)ο蟪绦蛟O(shè)計(jì)OOP的一個(gè)補(bǔ)充或擴(kuò)展,是為了解決OOP在一些共性問(wèn)題上的不足應(yīng)運(yùn)而生的。比如記錄日志、事務(wù)處理、性能分析等等與業(yè)務(wù)無(wú)關(guān)的需求,需要發(fā)生在很多類(lèi)的很多方法上,而需求

    2024年02月13日
    瀏覽(21)
  • Spring FrameWork從入門(mén)到NB -基于注解配置 & @Autowired注解

    基于注解的配置 其實(shí)前面我們已經(jīng)在基于注解配置了,這是由于個(gè)人比較喜歡基于注解配置。 Spring官方文檔提過(guò)一個(gè)問(wèn)題:基于注解配置要好于基于xml的配置嗎?其實(shí)各有千秋,根據(jù)個(gè)人喜好吧。重要的是Spring可以支持基于注解配置,也可以支持基于xml配置文件配置,也可

    2024年02月10日
    瀏覽(26)
  • Spring解決循環(huán)依賴(lài)

    Spring解決循環(huán)依賴(lài)

    目錄 什么是spring循環(huán)依賴(lài) 什么情況下循環(huán)依賴(lài)可以被處理? spring?如何解決循環(huán)依賴(lài) 創(chuàng)建A這個(gè)Bean的流程 答疑 疑問(wèn):在給B注入的時(shí)候?yàn)槭裁匆⑷胍粋€(gè)代理對(duì)象? 初始化的時(shí)候是對(duì)A對(duì)象本身進(jìn)行初始化,而容器中以及注入到B中的都是代理對(duì)象,這樣不會(huì)有問(wèn)題嗎? 三級(jí)

    2024年02月22日
    瀏覽(24)
  • Spring解決循環(huán)依賴(lài)問(wèn)題

    Spring解決循環(huán)依賴(lài)問(wèn)題

    例如,就是A對(duì)象依賴(lài)了B對(duì)象,B對(duì)象依賴(lài)了A對(duì)象。(下面的代碼屬于 屬性的循環(huán)依賴(lài) ,也就是初始化階段的循環(huán)依賴(lài),區(qū)別與底下 構(gòu)造器的循環(huán)依賴(lài) ) 問(wèn)題來(lái)了: A Bean創(chuàng)建 —— 依賴(lài)了 B 屬性 ——? 觸發(fā) B Bean創(chuàng)建 ——? B 依賴(lài)了 A 屬性 ——? 需要 A Bean(但A Bean還在創(chuàng)建

    2024年02月12日
    瀏覽(25)

覺(jué)得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請(qǐng)作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包