spring?Bean創(chuàng)建的完整過程記錄
前言
復(fù)習(xí)一下spring實現(xiàn)IOC的源碼流程準(zhǔn)備工作:
?強烈建議大家從git上拉取spring源碼來學(xué)習(xí)Spring源碼。因為里面相較于IDEA生成的會有注釋,里面有的方法會有注釋看起來會省力一點。
?以下都是用5.0.2版本來做闡述。
bean創(chuàng)建的流程圖
寫在前面:建議大家一定要自己用實例跑一遍,做好記錄。如果只是看看會非常抽象。此流程圖作為梗概,便于加強記憶和理解,新手或無基礎(chǔ)的有個印象即可。等跟隨本文走通一遍,在回過頭看這個圖,或許會有收獲
源碼走一遍bean的定義這是我的bean目錄結(jié)構(gòu),只是做一個例子
獲取核心容器對象,bean最后都會放在此容器對象中
* ApplicationContext的三個實現(xiàn)類 * ClassPathXmlApplicationContext 它可以加載類路徑下的配置文件,要求必須在類路徑下 * FileSystemXmlApplicationContext 可以加載任意路徑下的配置文件,必須有訪問權(quán)限 * AnnotationConfigApplicationContext 用于讀取注解創(chuàng)建容器的 這里我用ClassPathXmlApplicationContext來做演示 public class MyTest { public static void main(String[] args) { ApplicationContext context = new ClassPathXmlApplicationContext("bean.xml"); } }
快速開始
建議用IDEA的debug模式來觀察Spring的IOC過程
進入到此類的構(gòu)造方法中
查看setConfigLocations,就是將配置文件加載到configLocations里去
向下執(zhí)行,查看refresh()
this.prepareRefresh(): 此方法是準(zhǔn)備工作,大家感興趣可以點進去看一下,可以看到里面是獲取時間,獲取環(huán)境信息的一些設(shè)置。
this.obtainFreshBeanFactory(): 這一步是創(chuàng)建beanFactory,并且讀取Bean的信息,源碼注釋中還有寫到
// Tell the subclass to refresh the internal bean factory.會告訴子類去刷新內(nèi)部bean工廠
this.refreshBeanFactory:
* This implementation performs an actual refresh of this context's underlying * bean factory, shutting down the previous bean factory (if any) and * initializing a fresh bean factory for the next phase of the context's lifecycle. 這個實現(xiàn)類的方法會刷新容器中的beanFactory,關(guān)閉之前存在的并且初始化新的beanFactory
利用this.createBeanFactory() 創(chuàng)建了一個beanFactory,類型為DefaultListableBeanFactory
這個類接著往下走:this.loadBeanDefinitions(beanFactory);
* Load bean definitions into the given bean factory, typically through * delegating to one or more bean definition readers. 這個方法會將beandefinitionsReader讀取到的bean definitions放入bean工廠,我們以上提出的三種 注入方式都會走到這里,將bean信息丟進去
返回上述 refresh()
this.prepareBeanFactory(beanFactory); 設(shè)置和忽略一些對象值
this.postProcessBeanFactory(beanFactory); 空方法可自定義擴展
this.invokeBeanFactoryPostProcessors(beanFactory);
* Instantiate and invoke all registered BeanFactoryPostProcessor beans, * respecting explicit order if given. * <p>Must be called before singleton instantiation. 實例化所有beanFactory組件
registerBeanPostProcessors(beanFactory);
Instantiate and register all BeanPostProcessor beans, //先注冊再調(diào)用
initApplicationEventMulticaster(); 觀察者模式監(jiān)聽器, 監(jiān)聽組件的相關(guān)狀態(tài),并決定相關(guān)調(diào)用方法。
finishBeanFactoryInitialization(beanFactory); 重要??!
* Finish the initialization of this context's bean factory, * initializing all remaining singleton beans. 完成了容器bean factory的初始化,并且初始化其他的bean單例對象
beanFactory.preInstantiateSingletons(); 實例化方法
此方法最后this.getBean(beanName)
繼續(xù)
Return an instance, which may be shared or independent, of the specified bean. 注釋已經(jīng)很清楚了,此方法會返回一個實例,就是我們的bean對象
進入到createBean方法中
繼續(xù)進入
繼續(xù)進入
Instantiate the given bean using its default constructor. 這個方法注釋說明了實例化對象是用構(gòu)造器完成的
繼續(xù)看他如何構(gòu)造的
ca 就是Constructor,從這里我們基本可以看出容器內(nèi),bean對象的實例化 是利用反射的基本原理,獲取類構(gòu)造器,然后newInstance來實現(xiàn)的
以上就是bean對象實例化的基本過程,下面是實例化完成后的初始化過程
回到這里,實例化完成后
注釋說明了在populateBean完成bean的初始化
繼續(xù)
會看到在此方法里會調(diào)用前置和后置處理器來初始化Bean
以上就完成了bean的實例化過程,文章開頭的那個圖剛開始有點懵,但是一旦跑完一遍bean的實例化過程,再次結(jié)合圖,就清晰了很多。本文只是簡單的跟隨debug順序,完整的走了一遍bean實例化的過程,還有特殊情況并沒有討論,后期會重新用新文章再來拓展。
如有不足還請指正。
總結(jié)
到此這篇關(guān)于spring Bean創(chuàng)建的文章就介紹到這了,更多相關(guān)Spring Bean創(chuàng)建過程內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Eclipse中Debug時鼠標(biāo)懸停不能查看變量值解決辦法
這篇文章主要介紹了Eclipse中Debug時鼠標(biāo)懸停不能查看變量值解決辦法,以及分享了一個簡單補全代碼的方法,還是比較不錯的,需要的朋友可以參考下。2017-11-11java?啟動參數(shù)?springboot?idea詳解
這篇文章主要介紹了java?啟動參數(shù)?springboot?idea的相關(guān)知識,本文通過實例代碼給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2023-09-09Spring Boot異步調(diào)用@Async過程詳解
這篇文章主要介紹了Spring Boot異步調(diào)用@Async過程詳解,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下2019-11-11SpringCloud?Gateway實現(xiàn)API接口加解密
這篇文章主要為大家介紹了SpringCloud?Gateway如何實現(xiàn)API接口加解密的,文中的示例代碼講解詳細,對我們學(xué)習(xí)有一定的幫助,需要的可以參考一下2022-06-06