Bean實(shí)例化過(guò)程以及循環(huán)依賴

1. Bean創(chuàng)建

1. 實(shí)例化Bean

對(duì)于BeanFactory容器肋乍,當(dāng)客戶向容器請(qǐng)求一個(gè)尚未初始化的bean時(shí)揭朝,或初始化bean的時(shí)候需要注入另一個(gè)尚未初始化的依賴時(shí)队贱,容器就會(huì)調(diào)用createBean進(jìn)行實(shí)例化。對(duì)于ApplicationContext容器潭袱,當(dāng)容器啟動(dòng)結(jié)束后柱嫌,便實(shí)例化所有的bean。容器通過(guò)獲取BeanDefinition對(duì)象中的信息進(jìn)行實(shí)例化屯换。并且這一步僅僅是簡(jiǎn)單的實(shí)例化编丘,僅僅利用構(gòu)造函數(shù)通過(guò)反射實(shí)例化出對(duì)象与学,并未進(jìn)行依賴注入。

2. 依賴注入

實(shí)例化后的對(duì)象被封裝在BeanWrapper對(duì)象中嘉抓,并且此時(shí)對(duì)象仍然是一個(gè)原生的狀態(tài)索守,并沒(méi)有進(jìn)行依賴注入。緊接著Spring根據(jù)BeanDefinition中的信息進(jìn)行依賴注入抑片。并且通過(guò)BeanWrapper提供的設(shè)置屬性的接口完成依賴注入卵佛。如果此Bean的屬性的類型被注冊(cè)了屬性編輯器則會(huì)通過(guò)屬性編輯器實(shí)例化屬性。

3. Aware接口

緊接著敞斋,Spring會(huì)檢測(cè)該對(duì)象是否實(shí)現(xiàn)了xxxAware接口截汪,并調(diào)用相關(guān)的xxxAware實(shí)例的方法,這里的xxxAware有:BeanNameAware植捎、BeanClassLoaderAware衙解、BeanFactoryAware。

4. BeanPostProcessor前置處理器

接口BeanPostProcessor的方法postProcessBeforeInitialzation( Object bean, String beanName)開(kāi)始執(zhí)行焰枢。此方法返回bean實(shí)例蚓峦,也就是說(shuō)這里有機(jī)會(huì)更換實(shí)例,如果這里返回null則后面的BeanPostProcessor均不再進(jìn)行下去济锄。

5 InitializingBean暑椰、init-method

如果bean實(shí)現(xiàn)了InitializingBean接口或者指定了init-method,則afterPropertiesSet()或者指定初始化方法執(zhí)行荐绝。

6 BeanPostProcessor后置處理器

接口BeanPostProcessor的方法postProcessAfterInitialization( Object bean, String beanName)開(kāi)始執(zhí)行干茉。此方法返回bean實(shí)例,也就是說(shuō)這里有機(jī)會(huì)更換實(shí)例很泊,如果這里返回null則后面的BeanPostProcessor均不再進(jìn)行下去角虫。
4,5委造,6過(guò)程實(shí)現(xiàn)如下:
1戳鹅,applyBeanPostProcessorsBeforeInitialization(Object bean, String beanName)
2,invokeInitMethods(String, Object bean, RootBeanDefinition mbd)
3昏兆,applyBeanPostProcessorsAfterInitialization(Object bean, String beanName)

7. DisposableBean和destroy-method

注冊(cè)DisposableBean枫虏,當(dāng)調(diào)用Context的close()方法時(shí),如果bean實(shí)現(xiàn)了DisposableBean接口則會(huì)調(diào)用其destroy()方法爬虱,如果bean指定了destroy-method屬性則會(huì)調(diào)用其指定的方法隶债,如果二者都有則都會(huì)調(diào)用,如果destroy-method屬性值為(inferred)則close()和shutdown()方法被調(diào)用跑筝。注意:這個(gè)只針對(duì)scope為singleton的bean死讹,對(duì)于scope為prototype的bean不存在銷毀的說(shuō)法。

8. FactoryBean

如果bean實(shí)現(xiàn)了FactoryBean接口則會(huì)調(diào)用getObject()方法返回bean.

2. 循環(huán)依賴

1. A曲梗、B互相依賴且彼此均通過(guò)構(gòu)造函數(shù)注入赞警,則spring直接拋BeanCurrentlyInCreationException異常妓忍。
2. prototype bean之間不允許循環(huán)依賴,原理:

當(dāng)創(chuàng)建prototype bean時(shí)會(huì)先在ThreadLocal中找此bean的name是否存在如果存在則直接異常愧旦。例如:A世剖、B都為prototype且相互依賴,則創(chuàng)建流程為:

  1. 創(chuàng)建A對(duì)象笤虫,創(chuàng)建A對(duì)象前會(huì)判斷是否已經(jīng)創(chuàng)建旁瘫,判斷方法為在Thread Local對(duì)象中查找A名稱是否存在,第一次不存在所以此時(shí)把A名稱緩存至ThreadLocal琼蚯。
  2. A創(chuàng)建的過(guò)程中發(fā)現(xiàn)依賴B境蜕,則開(kāi)始創(chuàng)建B,B名稱緩存至ThreadLocal凌停。
  3. B創(chuàng)建的過(guò)程中發(fā)現(xiàn)依賴A,則開(kāi)始創(chuàng)建A售滤,此時(shí)發(fā)現(xiàn)ThreadLocal已經(jīng)緩存了A則直接拋出異常罚拟。
    如下圖:
    image
2. 單例默認(rèn)無(wú)參構(gòu)造函數(shù)允許循環(huán)依賴,其實(shí)現(xiàn)原理為三級(jí)緩存:
  1. 構(gòu)造函數(shù)實(shí)例化完成后緩存至singletonFactories集合完箩,此時(shí)雖然沒(méi)有完全走完實(shí)例化流程但是可以被其他bean注入赐俗。
  2. 在依賴注入階段第一次被其他bean注入則緩存至earlySingletonObjects并移除singletonFactories緩存。
  3. 最后創(chuàng)建完成緩存至singletonObjects集合并移除earlySingletonObjects緩存弊知。

例如有這樣的依賴關(guān)系:A依賴B阻逮、C,B秩彤、C依賴A叔扼。那么其創(chuàng)建過(guò)程如下:

  1. 請(qǐng)求A,在集合singletonObjects漫雷、earlySingletonObjects瓜富、singletonFactories中依次查找,發(fā)現(xiàn)沒(méi)有降盹。
  2. 開(kāi)始創(chuàng)建A与柑,先執(zhí)行構(gòu)造函數(shù)實(shí)例化A,把A緩存至singletonFactories中蓄坏。
  3. A注入B价捧,請(qǐng)求B,其過(guò)程同第1步請(qǐng)求A的過(guò)程涡戳。
  4. B注入A结蟋,請(qǐng)求A,此時(shí)A處于依賴注入階段并且第一次在此階段被請(qǐng)求渔彰,此時(shí)在集合singletonObjects椎眯、earlySingletonObjects挠将、singletonFactories中依次查找A,發(fā)現(xiàn)singletonFactories中存在A(第2步放進(jìn)去的)编整,此時(shí)將A從singletonFactories中移除并且緩存至earlySingletonObjects中舔稀,然后返回給B。
  5. B注入A結(jié)束掌测,B創(chuàng)建結(jié)束内贮,A注入B結(jié)束。
  6. A注入C汞斧,C的構(gòu)成過(guò)程同B夜郁。
  7. C注入A,請(qǐng)求A粘勒,此時(shí)在集合singletonObjects竞端、earlySingletonObjects、singletonFactories中依次查找庙睡,當(dāng)找到earlySingletonObjects時(shí)發(fā)現(xiàn)已經(jīng)存在了(第4步中放進(jìn)去的)事富,直接將A返回給C。
  8. C注入A結(jié)束乘陪,C創(chuàng)建結(jié)束统台,A注入C結(jié)束。
  9. 從earlySingletonObjects集合中移除A并緩存至singletonObjects啡邑。至此A贱勃、B、C創(chuàng)建完成谤逼。
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末贵扰,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子流部,更是在濱河造成了極大的恐慌拔鹰,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,755評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件贵涵,死亡現(xiàn)場(chǎng)離奇詭異列肢,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)宾茂,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,305評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門(mén)瓷马,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人跨晴,你說(shuō)我怎么就攤上這事欧聘。” “怎么了端盆?”我有些...
    開(kāi)封第一講書(shū)人閱讀 165,138評(píng)論 0 355
  • 文/不壞的土叔 我叫張陵怀骤,是天一觀的道長(zhǎng)费封。 經(jīng)常有香客問(wèn)我,道長(zhǎng)蒋伦,這世上最難降的妖魔是什么弓摘? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,791評(píng)論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮痕届,結(jié)果婚禮上韧献,老公的妹妹穿的比我還像新娘。我一直安慰自己研叫,他們只是感情好锤窑,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,794評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著嚷炉,像睡著了一般渊啰。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上申屹,一...
    開(kāi)封第一講書(shū)人閱讀 51,631評(píng)論 1 305
  • 那天绘证,我揣著相機(jī)與錄音,去河邊找鬼独柑。 笑死,一個(gè)胖子當(dāng)著我的面吹牛私植,可吹牛的內(nèi)容都是我干的忌栅。 我是一名探鬼主播,決...
    沈念sama閱讀 40,362評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼曲稼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼索绪!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起贫悄,我...
    開(kāi)封第一講書(shū)人閱讀 39,264評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤瑞驱,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后窄坦,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體唤反,經(jīng)...
    沈念sama閱讀 45,724評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,900評(píng)論 3 336
  • 正文 我和宋清朗相戀三年鸭津,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了彤侍。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,040評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡逆趋,死狀恐怖盏阶,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情闻书,我是刑警寧澤名斟,帶...
    沈念sama閱讀 35,742評(píng)論 5 346
  • 正文 年R本政府宣布脑慧,位于F島的核電站,受9級(jí)特大地震影響砰盐,放射性物質(zhì)發(fā)生泄漏闷袒。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,364評(píng)論 3 330
  • 文/蒙蒙 一楞卡、第九天 我趴在偏房一處隱蔽的房頂上張望霜运。 院中可真熱鬧,春花似錦蒋腮、人聲如沸淘捡。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,944評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)焦除。三九已至,卻和暖如春作彤,著一層夾襖步出監(jiān)牢的瞬間膘魄,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,060評(píng)論 1 270
  • 我被黑心中介騙來(lái)泰國(guó)打工竭讳, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留创葡,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,247評(píng)論 3 371
  • 正文 我出身青樓绢慢,卻偏偏與公主長(zhǎng)得像灿渴,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子胰舆,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,979評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容

  • 1. 詳解Spring 中如何控制2個(gè)bean中的初始化順序 ??開(kāi)發(fā)過(guò)程中有這樣一個(gè)場(chǎng)景骚露,2個(gè) bean 初始化...
    未名枯草閱讀 1,301評(píng)論 0 1
  • Spring容器的循環(huán)依賴檢測(cè) Spring容器循環(huán)依賴包括:構(gòu)造器循環(huán)依賴和setter循環(huán)依賴。 1- 構(gòu)造器...
    zhanglbjames閱讀 5,883評(píng)論 7 7
  • 本來(lái)是準(zhǔn)備看一看Spring源碼的缚窿。然后在知乎上看到來(lái)一個(gè)帖子棘幸,說(shuō)有一群**自己連Spring官方文檔都沒(méi)有完全讀...
    此魚(yú)不得水閱讀 6,935評(píng)論 4 21
  • 前幾天做了一場(chǎng)夢(mèng),有關(guān)姥姥的倦零。她坐在門(mén)口的小土墻上误续,一臉慈祥。醒來(lái)后扫茅,是宿舍高低床的床板女嘲,她的照片安靜地掛在墻的一...
    背著行囊的落二閱讀 229評(píng)論 0 5
  • 寫(xiě)了好幾天偽論文,到了關(guān)鍵時(shí)刻卻卡殼了诞帐,我承認(rèn)欣尼,還是有完美主義情結(jié),那就先放一放吧。感覺(jué)好久沒(méi)有寫(xiě)感悟愕鼓,怎么心里空...
    冠世墨玉yanzi閱讀 321評(píng)論 7 3