我們都知道BeanFactory和ApplicationContext是作為Spring IOC容器的頂層接口,其實不管是用默認的ClasspathXmlApplicationContext加載xml還是使用AnnotationAplicationContext通過Java Config方式啟動Spring,他們的過程其實都大同小異缅帘。本文就來分析下web環(huán)境下Spring容器的初始化缸逃。
首先啟動SpringBoot項目會執(zhí)行SpringApplication.run(App.class, args)预柒,進入方法內(nèi)部
首先我們先來看createApplicationContext方法,即進行IOC容器的創(chuàng)建,進入方法
我們發(fā)現(xiàn)他會根據(jù)是否為web環(huán)境創(chuàng)建容器掉伏。默認的web容器是AnnotationConfigEmbeddedWebApplicationContext。接著來看初始化方法澳窑,進入refreshContext(context)方法斧散,該方法為刷新容器的方法,一步步點進去摊聋,發(fā)現(xiàn)來到其父類AbstractApplicationContext的refresh()方法鸡捐,著重分析一下該方法。
1.首先來看prepareRefresh()方法麻裁,他主要做一些容器的準備
如圖箍镜,注釋已經(jīng)很清楚了,注意有個init方法煎源,記得我們以前開發(fā)時配置JDBC文件位置使用placeholder就是在這里進行注冊的色迂。
2.obtainFreshBeanFactory()方法主要做的工作就是銷毀之前的bean工廠并創(chuàng)建新的BeanFactory。
3.prepareBeanFactory(beanFactory);進行bean工廠的準備工作手销,主要為進行bean工廠的配置歇僧,注冊一些內(nèi)部bean。
4.postProcessBeanFactory(beanFactory);該方法允許子類進行beanFactory的修改锋拖。
5.invokeBeanFactoryPostProcessors(beanFactory);初始化并執(zhí)行容器中所有實現(xiàn)了BeanFactoryPostProcessor接口的bean诈悍。
6.registerBeanPostProcessors(beanFactory);注冊所有的BeanPostProcessor用于攔截bean的初始化祸轮,這是Spring給我們提供的擴展點之一。
這里需要注意一下的是侥钳,BeanPostProcessor其實可以指定順序的适袜,由方法可知他先注冊實現(xiàn)了PriorityOrdered接口的,再注冊實現(xiàn)了Ordered接口的最后注冊沒實現(xiàn)接口的舷夺。
7.initMessageSource();初始化國際化所使用的MessageSource痪蝇。
8.initApplicationEventMulticaster();初始化Spring的事件廣播器。
9.onRefresh();留給子類去實現(xiàn)用于初始化特定Context所需要的Bean冕房。
10.registerListeners();得到所有ApplicationListener并發(fā)布相應(yīng)的容器事件
11.finishBeanFactoryInitialization(beanFactory);結(jié)束beanFactory的創(chuàng)建并初始化容器中的非lazy單例bean躏啰,所有指定延遲加載為false的bean會在此處進行初始化。默認情況下是在啟動的時候進行加載所有bean耙册。
12.finishRefresh();最后一步
執(zhí)行相應(yīng)的生命周期方法并發(fā)布容器刷新事件给僵。
13.如果出異常進行容器的銷毀。
14.最后進行相關(guān)緩存的清空详拙。
至此Refresh方法已經(jīng)全部分析完了帝际。他是IOC容器創(chuàng)建的核心方法。
讓我們回到SpringApplication中的run方法饶辙,執(zhí)行完refreshContext(context)之后蹲诀,就是發(fā)布相應(yīng)SpringApplicationRunListener事件,最后返回創(chuàng)建的Context弃揽。
以上即為SpringIOC容器的創(chuàng)建過程分析
end脯爪。