Spring中的refresh方法分析
1 前言
在項目開發(fā)和面試過程中 spring
都是非常重要的,在前文中已經(jīng)講述了Spring BeanFactory 與 FactoryBean 的區(qū)別,在后續(xù)的文章中將繼續(xù)更新 Spring
源碼心得。了解原理性的一些內(nèi)容之后就會在應(yīng)用能夠得心應(yīng)手,在項目開發(fā)和面試中,就能很好地 battle 和 show muscle。
2 源碼入口哪里找
Spring 的源碼閱讀,需要找到入口文件,一般情況下在 Spring 項目中,由 tomcat 容器啟動后加載項目中設(shè)置的 web.xml,在改文件中添加項目的配置文件,監(jiān)聽器等內(nèi)容,其中 DispatcherServlet 尤為重要,其 onRefresh
方法就是其核心操作。不過隨著 springboot 的誕生,配置化的思想成型后,獲取源碼的入口就相對簡單了,核心需要關(guān)注 AbstractApplicationContext.refresh
。
獲取方法的入口常見的如下所示:
# 通過配置文件來讀取 ClassPathXmlApplicationContext ct = new ClassPathXmlApplicationContext("bean.xml"); # 通過配置類來加載 AnnotationConfigApplicationContext ct = new AnnotationConfigApplicationContext(MainConfig.class); # 兩者都是AbstractApplicationContext 的子類 AbstractApplicationContext
如下圖所示,通過配置文件來加載的 ClassPathXmlApplicationContext 是在構(gòu)造方法中調(diào)用了其父類的 refresh 方法,這個方法就是核心,就是大家都知道的 AbstractApplicationContext.refresh()
。
3 refresh 核心方法
關(guān)于源碼的閱讀,因其復(fù)雜的文件結(jié)構(gòu),在梳理其結(jié)構(gòu)時,需要抓大放小,不宜深入細(xì)節(jié),否則就容易迷路,不記得來時的路了。下圖便是核心方法 AbstractApplicationContext.refresh
對于 refresh 方法主要分為以下核心的 12 個方法:
- 1
prepareRefresh()
刷新前的預(yù)處理,調(diào)用 initPropertySources() 方法初始化一些屬性設(shè)置,調(diào)用 getEnvironment().validateRequiredProperties() 校驗屬性的合法性,設(shè)置 earlyApplicationEvents= new LinkedHashSet() 保存容器中較早期的事件。 - 2
obtainFreshBeanFactory()
獲取 BeanFactory,創(chuàng)建一個刷新的 Bean 工廠,refreshBeanFactory() 并設(shè)置容器 ID,然后將創(chuàng)建的 DefaultListableBeanFactory 的對象進(jìn)行返回。 - 3
prepareBeanFactory(beanFactory)
BeanFactory 的預(yù)準(zhǔn)備工作,設(shè)置 BeanFactory 的類加載器和表達(dá)式解析器,并添加 BeanPostProcessor【ApplicationContextAwareProcessor】,設(shè)置自動裝配的接口,添加 BeanPostProcessor。 - 4
postProcessBeanFactory(beanFactory)
BeanFactory 準(zhǔn)備工作完成后進(jìn)行的后置處理工作,子類通過重寫這個方法來做進(jìn)一步的設(shè)置。 - 5
invokeBeanFactoryPostProcessors(beanFactory)
執(zhí)行BeanFactoryPostProcessor 和 BeanFactory
方法的后置處理器。在BeanFactory
標(biāo)準(zhǔn)初始化之后執(zhí)行BeanFactoryPostProcessor
和BeanDefinitionRegistryPostProcessor
。先執(zhí)行BeanDefinitionRegistryPostProcessor.postProcessBeanDefinitionRegistry
方法,按照PriorityOrdered 、Ordered 和其它未設(shè)置優(yōu)先級
來執(zhí)行,然后按照同樣的優(yōu)先級來執(zhí)行BeanFactoryPostProcessor.postProcessBeanFactory
方法。 - 6
registerBeanPostProcessors(beanFactory)
注冊 BeanPostProcessor(Bean 的后置處理器),不同接口類型的BeanPostProcessor
在 Bean 創(chuàng)建前后的執(zhí)行時機(jī)是不一樣的。 - 7
initMessageSource()
初始化MessageSource
組件, 做國際化功能、消息綁定、消息解析等。 - 8
initApplicationEventMulticaster()
初始化事件派發(fā)器,如果容器中沒有事件派發(fā)器,那么就創(chuàng)建一個SimpleApplicationEventMulticaster
并添加到容器中。 - 9
onRefresh()
留給子容器(子類),例如在 springboot 中,用來創(chuàng)建 tomcat、jetty 容器并啟動。 - 10
registerListeners()
給容器中將所有項目里面的ApplicationListener
注冊進(jìn)來,并將監(jiān)聽器注冊到事件派發(fā)器中。 - 11
finishBeanFactoryInitialization(beanFactory)
初始化所有剩下的單實例 bean,這個方法是核心方法,在后續(xù)的主要流程中會詳細(xì)講解。 - 12
finishRefresh()
完成BeanFactory
的初始化創(chuàng)建工作,IOC 容器就創(chuàng)建完成。
4 總結(jié)
在本文中,講述了 Spring
容器啟動的核心方法 refresh
, 介紹了主要的啟動流程方法
以上就是Spring中的refresh方法分析的詳細(xì)內(nèi)容,更多關(guān)于spring refresh 方法的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
java8 stream 操作map根據(jù)key或者value排序的實現(xiàn)
這篇文章主要介紹了java8 stream 操作map根據(jù)key或者value排序的實現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-09-09SpringBoot整合Druid數(shù)據(jù)源過程詳解
這篇文章主要介紹了SpringBoot整合Druid數(shù)據(jù)源過程詳解,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下2019-12-12spring cloud中啟動Eureka Server的方法
本篇文章主要介紹了spring cloud中啟動Eureka Server的方法,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2018-01-01springboot2.6.3讀取不到nacos上的配置文件問題
這篇文章主要介紹了springboot2.6.3讀取不到nacos上的配置文件問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2023-07-07