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)建流程為:
- 創(chuàng)建A對(duì)象笤虫,創(chuàng)建A對(duì)象前會(huì)判斷是否已經(jīng)創(chuàng)建旁瘫,判斷方法為在Thread Local對(duì)象中查找A名稱是否存在,第一次不存在所以此時(shí)把A名稱緩存至ThreadLocal琼蚯。
- A創(chuàng)建的過(guò)程中發(fā)現(xiàn)依賴B境蜕,則開(kāi)始創(chuàng)建B,B名稱緩存至ThreadLocal凌停。
- 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í)緩存:
- 構(gòu)造函數(shù)實(shí)例化完成后緩存至singletonFactories集合完箩,此時(shí)雖然沒(méi)有完全走完實(shí)例化流程但是可以被其他bean注入赐俗。
- 在依賴注入階段第一次被其他bean注入則緩存至earlySingletonObjects并移除singletonFactories緩存。
- 最后創(chuàng)建完成緩存至singletonObjects集合并移除earlySingletonObjects緩存弊知。
例如有這樣的依賴關(guān)系:A依賴B阻逮、C,B秩彤、C依賴A叔扼。那么其創(chuàng)建過(guò)程如下:
- 請(qǐng)求A,在集合singletonObjects漫雷、earlySingletonObjects瓜富、singletonFactories中依次查找,發(fā)現(xiàn)沒(méi)有降盹。
- 開(kāi)始創(chuàng)建A与柑,先執(zhí)行構(gòu)造函數(shù)實(shí)例化A,把A緩存至singletonFactories中蓄坏。
- A注入B价捧,請(qǐng)求B,其過(guò)程同第1步請(qǐng)求A的過(guò)程涡戳。
- 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。
- B注入A結(jié)束掌测,B創(chuàng)建結(jié)束内贮,A注入B結(jié)束。
- A注入C汞斧,C的構(gòu)成過(guò)程同B夜郁。
- C注入A,請(qǐng)求A粘勒,此時(shí)在集合singletonObjects竞端、earlySingletonObjects、singletonFactories中依次查找庙睡,當(dāng)找到earlySingletonObjects時(shí)發(fā)現(xiàn)已經(jīng)存在了(第4步中放進(jìn)去的)事富,直接將A返回給C。
- C注入A結(jié)束乘陪,C創(chuàng)建結(jié)束统台,A注入C結(jié)束。
- 從earlySingletonObjects集合中移除A并緩存至singletonObjects啡邑。至此A贱勃、B、C創(chuàng)建完成谤逼。