前言
- 上篇博客spring 5.0.x源碼學(xué)習(xí)系列七: 后置處理器ConfigurationClassPostProcessor之BeanFactoryPostProcessor身份主要介紹了ConfigurationClassPostProcessor的BeanFactoryPostProcessor身份持灰。接下來(lái),將進(jìn)入spring最核心的
bean實(shí)例化
過(guò)程节槐。
一配乱、解析構(gòu)建bean過(guò)程
- 構(gòu)建bean的過(guò)程太復(fù)雜,將根據(jù)我自己寫的流程圖來(lái)一一講解
1.1 流程圖
1.2 流程圖解析
1.2.1 創(chuàng)建非抽象于毙、單例敦冬、非懶加載的bean
整個(gè)正常流程是遍歷bean工廠存放beanName的list, 并根據(jù)beanName拿到對(duì)應(yīng)的beanDefinition,只過(guò)濾掉非抽象
唯沮、單例
脖旱、非懶加載
的beand進(jìn)行創(chuàng)建
1.2.2 判斷當(dāng)前創(chuàng)建bean的類型并作相應(yīng)處理
因?yàn)閟pring存在兩種bean, 普通bean和FactoryBean,spring在區(qū)分這兩種bean的做法是beanName和beanType來(lái)雙重校驗(yàn)的介蛉。假設(shè)獲取的bean為FactoryBean萌庆,那么會(huì)在getBean之前在beanName前添加一個(gè)&
符號(hào)
if (isFactoryBean(beanName)) {
// org.springframework.beans.factory.BeanFactory#FACTORY_BEAN_PREFIX
// String FACTORY_BEAN_PREFIX = "&";
Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
// 后面的邏輯省略
}
1.2.3 getBean <=> doGetBean獲取bean的通用方法
- 此方法是spring根據(jù)beanName獲取bean的通用方法。在此方法中有兩個(gè)地方需要注意:
- 內(nèi)部會(huì)對(duì)傳入的beanName做處理(將傳入的beanName前面的
&
符號(hào)去掉并存入內(nèi)部自己維護(hù)的一個(gè)變量中)币旧, 此時(shí)關(guān)于當(dāng)前bean的名稱會(huì)有兩個(gè)變量存儲(chǔ)践险,分別是name(方法傳入的bean名稱), beanName(處理過(guò)bean名稱) - 不管是從bean工廠的單例池中獲取還是新建的bean, 最終都要走
getObjectForBeanInstance
方法來(lái)返回bean。這樣做主要是為了處理獲取的bean類型為FactoryBean的情況吹菱。
具體規(guī)則可參考此鏈接:https://github.com/AvengerEug/spring/tree/develop/resourcecode-study#%E5%8D%81%E4%B8%80-%E8%8E%B7%E5%8F%96factorybean%E5%AE%9E%E4%BE%8B%E4%B8%8E%E5%AE%83%E7%BB%B4%E6%8A%A4%E7%9A%84bean%E5%AE%9E%E4%BE%8B%E8%A7%84%E5%88%99
1.2.4 第一次getSingleon
- 此方法很重要
- 正常邏輯(循環(huán)bean工廠挨個(gè)創(chuàng)建bean)進(jìn)來(lái), 這里獲取的值肯定為null
- 在populateBean自動(dòng)裝配需要?jiǎng)?chuàng)建依賴bean時(shí), 這里獲取的可能為null也可能不為null. 只有在循環(huán)依賴和spring單例池存在bean的情況下, 獲取的才不為null, 因?yàn)榇朔椒〞?huì)首先從單例池中獲取bean, 若不存在再根據(jù)這個(gè)bean是否正在被創(chuàng)建從而到"特殊"(根據(jù)beanName到singletonFactories拿ObjectFactory, 并根據(jù)ObjectFactory獲取bean巍虫。
public Object getSingleton(String beanName)
1.2.5 第二次調(diào)用getSingleton
- 此方法只有在創(chuàng)建新的bean時(shí)才會(huì)用到,傳入的ObjectFactory是當(dāng)前類的createBean方法
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory)
1.2.6 getSingleton內(nèi)部的beforeSingletonCreation方法
-
標(biāo)記bean正在被創(chuàng)建:
此動(dòng)作很重要, 主要是將beanName存放至DefaultSingletonBeanRegistry類的singletonsCurrentlyInCreation數(shù)據(jù)結(jié)構(gòu)(Set<String>), 后續(xù)會(huì)根據(jù)這個(gè)依據(jù)來(lái)解決循環(huán)依賴的情況, 即上述1.2.4 第一次getSingleon中所說(shuō)的獲取不為null的情況protected void beforeSingletonCreation(String beanName) { if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.add(beanName)) { throw new BeanCurrentlyInCreationException(beanName); } }
1.2.7 調(diào)用傳入的createBean方法<=>singletonFactory.getObject()
- 內(nèi)部會(huì)調(diào)用至doCreateBean方法
1.2.8 doCreateBean方法
- 內(nèi)部會(huì)創(chuàng)建出來(lái)bean, 創(chuàng)建完后還會(huì)在此方法中進(jìn)行自動(dòng)裝配populateBean
1.2.9 createBeanInstance方法
- 此方法為真正創(chuàng)建bean的流程鳍刷,內(nèi)部主要做了如下事情
-
確定當(dāng)前bean是否通過(guò)構(gòu)造方法自動(dòng)裝配, 源碼和條件如下:
Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName); if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR || mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) { return autowireConstructor(beanName, mbd, ctors, args); }
1. ctors != null => ctors中存的是構(gòu)造方法中添加@Autowired注解的情形 2. mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR => 此條件為使用后置處理器手動(dòng)修改beanDefinition的自動(dòng)裝配的值, 默認(rèn)為no 3. mbd.hasConstructorArgumentValues() => 使用后置處理器手動(dòng)添加beanDefinition中存放構(gòu)造方法值的情形, eg: mybatis中的definition.getConstructorArgumentValues().addGenericArgumentValue(definition.getBeanClassName()); 4. !ObjectUtils.isEmpty(args) 上述條件只要滿足一個(gè)就走構(gòu)造方法自動(dòng)裝配的邏輯 ```
若使用構(gòu)造方法自動(dòng)裝配的結(jié)論不成立則走默認(rèn)構(gòu)造方法創(chuàng)建bean流程
不管是默認(rèn)構(gòu)造方法創(chuàng)建bean還是通過(guò)構(gòu)造方法自動(dòng)裝配bean占遥,所有bean的創(chuàng)建使用的都是CglibSubclassingInstantiationStrategy策略
1.2.10 確認(rèn)當(dāng)前bean是否符合循環(huán)依賴的情況 <=> addSingletonFactory方法
- 滿足循環(huán)依賴的三個(gè)條件: 單例、allowCircularReferences為true输瓜、當(dāng)前的bean正在創(chuàng)建中
protected void addSingletonFactory(String beanName, ObjectFactory<?> singletonFactory) { Assert.notNull(singletonFactory, "Singleton factory must not be null"); synchronized (this.singletonObjects) { if (!this.singletonObjects.containsKey(beanName)) { // 存放bean對(duì)應(yīng)的ObjectFactory, 在bean的循環(huán)依賴中會(huì)用上 this.singletonFactories.put(beanName, singletonFactory); this.earlySingletonObjects.remove(beanName); // 存放已經(jīng)被注冊(cè)過(guò)的bean this.registeredSingletons.add(beanName); } } }
- 使用構(gòu)造方法創(chuàng)建bean后, 會(huì)做三個(gè)操作:
this.singletonFactories.put(beanName, singletonFactory);
=> 在getBean方法的第一次getSingleton中會(huì)用到瓦胎,其實(shí)這個(gè)singletonFactory的形參中已經(jīng)在創(chuàng)建bean的過(guò)程中傳入了,并且內(nèi)部的邏輯是執(zhí)行SmartInstantiationAwareBeanPostProcessor后置處理器的getEarlyBeanReference方法尤揣,此方法可以返回一個(gè)bean
)的地方去拿beanthis.earlySingletonObjects.remove(beanName);
-
this.registeredSingletons.add(beanName); => 此步驟只是為了記錄這個(gè)bean已經(jīng)被spring創(chuàng)建了或者正在被創(chuàng)建中
所以創(chuàng)建一個(gè)bean后(還未依賴注入bean), 會(huì)在singletonFactories和registeredSingletons數(shù)據(jù)結(jié)構(gòu)中都存在相關(guān)記錄
1.2.11 自動(dòng)裝配 <=> populateBean方法
- 此方法中主要是
AutowiredAnnotationBeanPostProcessor
后置處理器來(lái)實(shí)現(xiàn)自動(dòng)裝配搔啊,若bean需要自動(dòng)裝配,則還需要先實(shí)例化依賴的bean芹缔,最終又會(huì)走到上述getBean邏輯
1.2.12 bean創(chuàng)建完畢, 開始執(zhí)行bean的一些后置處理器
- 調(diào)用bean的
BeanPostProcessor
后置處理器postProcessBeforeInitialization方法 - 若bean實(shí)現(xiàn)了
InitializingBean
接口, 則調(diào)用接口中的方法afterPropertiesSet - 調(diào)用bean的
BeanPostProcessor
后置處理器de postProcessAfterInitialization方法
1.2.13 清除bean正在創(chuàng)建的標(biāo)識(shí)并添加至bean工廠
- afterSingletonCreation
// this.singletonsCurrentlyInCreation.remove(beanName) => 移除當(dāng)前bean name
protected void afterSingletonCreation(String beanName) {
if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.remove(beanName)) {
throw new IllegalStateException("Singleton '" + beanName + "' isn't currently in creation");
}
}
- addSingleton
protected void addSingleton(String beanName, Object singletonObject) {
synchronized (this.singletonObjects) {
// bean工廠單例池
this.singletonObjects.put(beanName, singletonObject);
// 執(zhí)行到這表示當(dāng)前bean已經(jīng)創(chuàng)建完成, 則移除循環(huán)依賴的bean的情況,
// 若下次還有bean依賴它, 直接從bean工廠的單例池獲取即可
this.singletonFactories.remove(beanName);
// 當(dāng)前bean被創(chuàng)建完畢坯癣,則清除它
this.earlySingletonObjects.remove(beanName);
// 再次將bean添加至該集合中, 該集合是一個(gè)set, 不會(huì)重復(fù), 這里重復(fù)添加的原因可能是并發(fā)情況
this.registeredSingletons.add(beanName);
}
}
二瓶盛、一個(gè)案例搞清楚循環(huán)依賴
2.1 案例背景
- 有兩個(gè)類: A和B最欠,它們互相依賴(A中要自動(dòng)裝配B屬性,B中要自動(dòng)裝配A屬性), 假設(shè)先創(chuàng)建A
2.2 流程
- 創(chuàng)建Bean a <=> getBean("a")
第一次調(diào)用getSingleton方法, 單例池中無(wú)bean a 惩猫,也沒(méi)標(biāo)識(shí)正在被創(chuàng)建, 所以走第二個(gè)getSingleton方法芝硬。此時(shí)a被標(biāo)注正在被創(chuàng)建走使用構(gòu)造方法創(chuàng)建bean的邏輯 - 在創(chuàng)建完a后開始記錄bean a的一些狀態(tài)(
將bean name添加至registeredSingletons以及將bean對(duì)應(yīng)的ObjectFactory添加至singletonFactories。即上述的addSingletonFactory方法的操作
)和填充屬性, 發(fā)現(xiàn)它依賴于B, 此時(shí)要去getBean(b) - 然后進(jìn)入創(chuàng)建bean b流程 <=> getBean("b")
- 此時(shí)會(huì)進(jìn)入第一個(gè)getSingleton方法, 此時(shí)spring單例池中無(wú)b并且b也還未被標(biāo)注為被創(chuàng)建(因?yàn)樗窃趃etSingleton方法后面標(biāo)注的)狀態(tài)所以進(jìn)入創(chuàng)建createBean方法
- 同理, 在創(chuàng)建完b后也會(huì)記錄bean b的一些狀態(tài)(
將bean name添加至registeredSingletons以及將bean對(duì)應(yīng)的ObjectFactory添加至singletonFactories轧房。即上述的addSingletonFactory方法的操作
) - 創(chuàng)建完b后開始填充屬性, 發(fā)現(xiàn)它又依賴于A, 此時(shí)要去getBean("a")
- 此時(shí)進(jìn)入第一個(gè)getSingleton方法,
發(fā)現(xiàn)單例池中無(wú)a(雖然a在上述過(guò)程中被創(chuàng)建了, 但是它還未放入單例池中)但是它是處于被創(chuàng)建的狀態(tài), 所以從singletonFactories中根據(jù)beanName拿ObjectFactory, 最終從ObjectFactory拿到Bean a
, 并將singletonFactories中beanName對(duì)應(yīng)的objectFactory remove掉,以及將拿到的bean a放入到earlySingletonObjects中 - 最終拿到了bean a, 此時(shí)將bean a注入到bean b中的a屬性中, 完成bean b的創(chuàng)建(此時(shí)會(huì)將它正在創(chuàng)建的標(biāo)識(shí)移除并它放入單例池中去), 并調(diào)用BeanPostProcessor后置處理器以及InitializingBean接口的afterPropertiesSet方法, 至此bean b的創(chuàng)建結(jié)束了 返回bean b拌阴。
- 因?yàn)樯鲜鰟?chuàng)建bean b的過(guò)程是a要自動(dòng)裝配b而執(zhí)行的, 為的就是獲取bean b。現(xiàn)在已經(jīng)拿到bean b了, 所以將bean a中的b屬性給注入進(jìn)去, 最終完成bean a的創(chuàng)建, 將a也添加到spring單例池中并調(diào)用BeanPostProcessor后置處理器以及InitializingBean接口的afterPropertiesSet方法
- bean a創(chuàng)建完成奶镶,循環(huán)依賴步驟完成
- 涉及到的幾個(gè)數(shù)據(jù)結(jié)構(gòu):
-
registeredSingletons
: 表示該bean已經(jīng)通過(guò)構(gòu)造方法創(chuàng)建出來(lái)了 -
singletonFactories
: 存放bean對(duì)應(yīng)的objectFactory方法, 循環(huán)依賴時(shí)需要根據(jù)它來(lái)拿bean -
earlySingletonObjects
: 與singletonFactories的操作是互斥的, 里面存放的是singletonFactories中beanName對(duì)應(yīng)的objectFactory創(chuàng)建出來(lái)的bean,若一個(gè)beanName在該集合中存在, 那么該bean對(duì)應(yīng)的ObjectFactory就會(huì)在singletonFactories中被remove掉 -
singletonsCurrentlyInCreation
: 表示當(dāng)前bean正在被創(chuàng)建, 在getSingleton(String beanName, ObjectFactory<?> singletonFactory)方法中進(jìn)行操作, 添加迟赃、移除正在創(chuàng)建的標(biāo)識(shí)都是在此方法中完成
-
三陪拘、spring bean實(shí)例化過(guò)程中涉及到的后置處理器和執(zhí)行順序
執(zhí)行順序 | 執(zhí)行位置 | 執(zhí)行到的后置處理器 | 執(zhí)行的方法 | 作用 |
---|---|---|---|---|
1 | org.springframework.beans.factory.support. AbstractAutowireCapableBeanFactory.doCreateBean => resolveBeforeInstantiation方法 |
InstantiationAwareBeanPostProcessor | 1. postProcessBeforeInstantiation 2.postProcessAfterInitialization |
1. postProcessBeforeInstantiation作用: 若后置處理器中返回了一個(gè)對(duì)象, 則不會(huì)走spring的創(chuàng)建bean的流程 2.若postProcessBeforeInstantiation方法返回的bean不為null則執(zhí)行postProcessAfterInitialization方法,該方法執(zhí)行了BeanPostProcessor后置處理器, 自動(dòng)裝配的后置處理器就間接實(shí)現(xiàn)了BeanPostProcessor, 若BeanPostProcessor不被執(zhí)行, 那么自動(dòng)裝配的功能也將缺失 3. 若bean中實(shí)現(xiàn)了aware接口纤壁,那么將按照aware的類型誒個(gè)執(zhí)行對(duì)應(yīng)的方法左刽,其中就包括獲取spring上下文的ApplicationContextAware |
2 | org.springframework.beans.factory.support. AbstractAutowireCapableBeanFactory.createBeanInstance => determineConstructorsFromBeanPostProcessors |
SmartInstantiationAwareBeanPostProcessor | determineCandidateConstructors | 掃描當(dāng)前bean攜帶@Autowired注解的構(gòu)造方法或者只有一個(gè)帶參的構(gòu)造方法或者等等其他的情況。(具體參考AutowiredAnnotationBeanPostProcessor類的determineCandidateConstructors方法) |
3 | org.springframework.beans.factory.support. AbstractAutowireCapableBeanFactory.doCreateBean => applyMergedBeanDefinitionPostProcessors |
MergedBeanDefinitionPostProcessor | postProcessMergedBeanDefinition | 將當(dāng)前類需要自動(dòng)裝配的屬性全部InjectionMetadata對(duì)象中(每個(gè)屬性對(duì)應(yīng)一個(gè)InjectionMetadata對(duì)象) |
4 | org.springframework.beans.factory.support. AbstractAutowireCapableBeanFactory.doCreateBean => getEarlyBeanReference |
SmartInstantiationAwareBeanPostProcessor | getEarlyBeanReference | 當(dāng)處理循環(huán)依賴時(shí)酌媒,會(huì)獲取到狀態(tài)為'正在創(chuàng)建'的bean的引用 |
5 | org.springframework.beans.factory.support. AbstractAutowireCapableBeanFactory.populateBean => postProcessAfterInstantiation |
InstantiationAwareBeanPostProcessor | postProcessAfterInstantiation | 能夠控制當(dāng)前bean是否繼續(xù)完成依賴注入邏輯欠痴,若方法return false,則當(dāng)前bean的@Autowired注解功能的依賴注入結(jié)束 |
6 | org.springframework.beans.factory.support. AbstractAutowireCapableBeanFactory.populateBean => postProcessPropertyValues |
InstantiationAwareBeanPostProcessor | postProcessPropertyValues | 處理當(dāng)前bean自動(dòng)裝配的屬性 |
7 | org.springframework.beans.factory.support. AbstractAutowireCapableBeanFactory.initializeBean => applyBeanPostProcessorsBeforeInitialization |
BeanPostProcessor | postProcessBeforeInitialization | 當(dāng)bean被實(shí)例化并完成自動(dòng)裝配之后執(zhí)行 |
8 | org.springframework.beans.factory.support. AbstractAutowireCapableBeanFactory.initializeBean => applyBeanPostProcessorsAfterInitialization |
BeanPostProcessor | postProcessAfterInitialization | 當(dāng)bean被實(shí)例化并完成自動(dòng)裝配之后執(zhí)行秒咨,比postProcessBeforeInitialization方法后執(zhí)行 |
- 如上, 一共會(huì)執(zhí)行4個(gè)后置處理器InstantiationAwareBeanPostProcessor, SmartInstantiationAwareBeanPostProcessor, MergedBeanDefinitionPostProcessor, BeanPostProcessor, 共執(zhí)行了8次, 其中InstantiationAwareBeanPostProcessor類型的后置處理器調(diào)用次數(shù)最多, 8次調(diào)用中有5次跟它有關(guān), 因?yàn)樗^承了
BeanPostProcessor
, 并擴(kuò)展了三個(gè)方法postProcessBeforeInstantiation喇辽、 postProcessAfterInstantiation和postProcessPropertyValues
四、小結(jié)
- 本篇博客還有很多細(xì)節(jié)未提及雨席,比如spring如何知道使用哪一個(gè)構(gòu)造方法(假設(shè)程序員提供了多個(gè)構(gòu)造器)創(chuàng)建bean菩咨、自動(dòng)裝配后置處理器AutowiredAnnotationBeanPostProcessor是如何知道哪些屬性需要裝配哪些不需要、在5個(gè)后置處理器的八個(gè)地方被調(diào)用的具體作用和景點(diǎn)案例也未完全總結(jié)等等舅世。只能等日后再完善了
- I am a slow walker, but I never walk backwards.
- github spring源碼學(xué)習(xí)地址: https://github.com/AvengerEug/spring/tree/develop/resourcecode-study