Spring 中循環(huán)依賴是如何解決半抱?

注: 本文安裝bean生成經(jīng)過緩存的順序標(biāo)注
一級緩存 singletonObjects 緩存加載完成的bean脓恕。

二級緩存 singletonFactories 。緩存一個objectFactory工廠窿侈。

三級緩存 earlySingletonObjects 獲取到的bean炼幔。

1. 什么是spring 循環(huán)引用?

@Configurable
@ComponentScan("com.shadow")
public class Appconfig {
}

@Component
public class X {

    @Autowired
    Y y;

    public X(){
        System.out.println("X create");
    }
}


@Component
public class Y {
    @Autowired
    X x;
    
    public Y(){
        System.out.println("Y create");
    }
}

就是相互引用了對方史简,也就是我們常常的說的循環(huán)依賴.

spring 默認是支持單利的循環(huán)引用乃秀。

2. 怎么關(guān)閉spring的循環(huán)依賴?

    boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
            isSingletonCurrentlyInCreation(beanName));

支持不支持循環(huán)引用this.allowCircularReferences這個參數(shù)圆兵,可以在之前將參數(shù)修改為false;

可以修改源碼跺讯,或者使用注冊器注入;

3. spring bean 解析初始化生命周期的過程殉农;

解析.class
  1. 實例化一個ApplicationContext的對象刀脏;
  2. 調(diào)用bean工廠后置處理器完成掃描;@service,@controller, @Import,@Bean 實質(zhì)上都是工廠后置處理器的不同實現(xiàn)超凳。
  3. 循環(huán)解析掃描出來的類信息愈污;
  4. 實例化一個BeanDefinition對象來存儲解析出來的信息;
  5. 把實例化好的beanDefinition對象put到beanDefinitionMap當(dāng)中緩存起來聪建,以便后面實例化bean钙畔;
  6. 再次調(diào)用bean工廠后置處理器,這次我們程序員可以調(diào)用工廠后置處理器,在bean創(chuàng)建前再對bean的scop,class,構(gòu)造參數(shù)等進行修改金麸,spring-mybatis就是在這里擎析,將class換了;
初始化和bean生命周期
  1. 如果驗證完成spring在實例化一個bean之前需要推斷構(gòu)造方法,因為spring實例化對象是通過構(gòu)造方法反射揍魂,故而需要知道用哪個構(gòu)造方法桨醋;
  2. 推斷完構(gòu)造方法之后spring調(diào)用構(gòu)造方法反射實例化一個對象;注意我這里說的是對象现斋、對象喜最、對象;這個時候?qū)ο笠呀?jīng)實例化出來了庄蹋,但是并不是一個完整的bean瞬内,最簡單的體現(xiàn)是這個時候?qū)嵗鰜淼膶ο髮傩允菦]有注入,所以不是一個完整的bean限书;
  3. spring處理合并后的beanDefinition虫蝶;
  4. 判斷是否支持循環(huán)依賴,如果支持則提前把一個工廠存入singletonFactories——map倦西;
  5. 判斷是否需要完成屬性注入
  6. 如果需要完成屬性注入能真,則開始注入屬性
  7. 判斷bean的類型回調(diào)Aware接口
    15:調(diào)用生命周期回調(diào)方法,在初始化前后進行調(diào)用bean的后置處理器扰柠;前面試bean工廠后置處理器粉铐;
    16:如果需要代理則完成代理
    17:put到單例池——bean完成——存在spring容器當(dāng)中

Spring 循環(huán)依賴的過程

  1. getSingleton() 嘗試去singletonObjects中獲取對象。
  2. 沒有卤档,則進行beforeSingletonCreate,將bean的名稱加入正在創(chuàng)建bean的集合蝙泼,表明這個bean正在創(chuàng)建;
  3. 通過doCreateBean創(chuàng)建對象裆装,使用反射進行創(chuàng)建踱承;
  4. 再次判斷是單利&支持循環(huán)依賴&正在創(chuàng)建,而此時是new 出對象了哨免,封裝到FactoryBean 對象中茎活,并將其加入 singletonFactories,二級緩存工廠;
  5. 這時候可以進行bean的屬性填充琢唾,進行依賴填充y類载荔,所以y也要走上面的流程,但是走到1采桃, getSingleton()是可以返回對象的懒熙,主要其中有判斷對方正在創(chuàng)建,然后從singletonFactories普办,二級緩存工廠里拿到bean; 同時將bean從二級緩存然后從singletonFactories刪除工扎,put進去三級緩存,ealySingletonObjects ,完成循環(huán)依賴注入衔蹲;
為什么首先是從三級緩存中取呢肢娘?

主要是為了性能,因為三級緩存中存的是一個x對象,如果能取到則不去二級找了橱健;

為什么一開始要存二級緩存工廠呢而钞?為什么一開始不直接存三級緩存?

如果直接存到三級緩存拘荡,只能存一個對象臼节,假設(shè)以前存這個對象的時候這對象的狀態(tài)為xa,但是我們這里y要注入的x為xc狀態(tài)珊皿,那么則無法滿足网缝;但是如果存一個工廠,工廠根據(jù)情況產(chǎn)生任意xa或者xb或者xc等等情況亮隙;比如說aop的情況下x注入y途凫,y也注入x垢夹;而y中注入的x需要加代理(aop)

為什么要從二級緩存remove溢吻?

因為如果存在比較復(fù)雜的循環(huán)依賴可以提高性能;比如x果元,y促王,z相互循環(huán)依賴,那么第一次y注入x的時候從二級緩存通過工廠返回了一個x而晒,放到了三級緩存蝇狼,而第二次z注入x的時候便不需要再通過工廠去獲得x對象了。因為if分支里面首先是訪問三級緩存倡怎;至于remove則是為了gc吧迅耘;

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市监署,隨后出現(xiàn)的幾起案子颤专,更是在濱河造成了極大的恐慌,老刑警劉巖钠乏,帶你破解...
    沈念sama閱讀 216,402評論 6 499
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件栖秕,死亡現(xiàn)場離奇詭異,居然都是意外死亡晓避,警方通過查閱死者的電腦和手機簇捍,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,377評論 3 392
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來俏拱,“玉大人暑塑,你說我怎么就攤上這事」兀” “怎么了事格?”我有些...
    開封第一講書人閱讀 162,483評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我分蓖,道長尔艇,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,165評論 1 292
  • 正文 為了忘掉前任么鹤,我火速辦了婚禮终娃,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘蒸甜。我一直安慰自己棠耕,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,176評論 6 388
  • 文/花漫 我一把揭開白布柠新。 她就那樣靜靜地躺著窍荧,像睡著了一般。 火紅的嫁衣襯著肌膚如雪恨憎。 梳的紋絲不亂的頭發(fā)上蕊退,一...
    開封第一講書人閱讀 51,146評論 1 297
  • 那天,我揣著相機與錄音憔恳,去河邊找鬼瓤荔。 笑死,一個胖子當(dāng)著我的面吹牛钥组,可吹牛的內(nèi)容都是我干的输硝。 我是一名探鬼主播,決...
    沈念sama閱讀 40,032評論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼程梦,長吁一口氣:“原來是場噩夢啊……” “哼点把!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起屿附,我...
    開封第一講書人閱讀 38,896評論 0 274
  • 序言:老撾萬榮一對情侶失蹤郎逃,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后拿撩,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體衣厘,經(jīng)...
    沈念sama閱讀 45,311評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,536評論 2 332
  • 正文 我和宋清朗相戀三年压恒,在試婚紗的時候發(fā)現(xiàn)自己被綠了影暴。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,696評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡探赫,死狀恐怖型宙,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情伦吠,我是刑警寧澤妆兑,帶...
    沈念sama閱讀 35,413評論 5 343
  • 正文 年R本政府宣布魂拦,位于F島的核電站,受9級特大地震影響搁嗓,放射性物質(zhì)發(fā)生泄漏芯勘。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,008評論 3 325
  • 文/蒙蒙 一腺逛、第九天 我趴在偏房一處隱蔽的房頂上張望荷愕。 院中可真熱鬧,春花似錦棍矛、人聲如沸箕戳。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,659評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽没佑。三九已至剩拢,卻和暖如春剔难,著一層夾襖步出監(jiān)牢的瞬間劝评,已是汗流浹背因惭。 一陣腳步聲響...
    開封第一講書人閱讀 32,815評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留脐雪,地道東北人厌小。 一個月前我還...
    沈念sama閱讀 47,698評論 2 368
  • 正文 我出身青樓,卻偏偏與公主長得像战秋,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子讨韭,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,592評論 2 353