??springboot在啟動的時候,會調(diào)用run方法,創(chuàng)建環(huán)境設(shè)置spring容器,其中包含refresh方法,完成配置類解析,各種beanFactoryPostProcess和beanPostProcessor注冊,web內(nèi)置容器構(gòu)造,國際化配置初始化等,refresh調(diào)用了父類AbstractApplicationContext的refresh方法如下。
@Override
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// 準(zhǔn)備,記錄容器的啟動時間startupDate, 標(biāo)記容器為激活,初始化上下文環(huán)境如文件路徑信息,驗(yàn)證必填屬性是否填寫
prepareRefresh();
// 這步比較重要(解析),告訴子類去刷新bean工廠,這步完成后配置文件就解析成一個個bean定義,注冊到BeanFactory(但是未被初始化,僅將信息寫到了beanDefination的map中)
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// 設(shè)置beanFactory類加載器,添加多個beanPostProcesser
prepareBeanFactory(beanFactory);
try {
// 允許子類上下文中對beanFactory做后期處理
postProcessBeanFactory(beanFactory);
// 調(diào)用BeanFactoryPostProcessor各個實(shí)現(xiàn)類的方法
invokeBeanFactoryPostProcessors(beanFactory);
// 注冊 BeanPostProcessor 的實(shí)現(xiàn)類,注意看和 BeanFactoryPostProcessor 的區(qū)別
// 此接口兩個方法: postProcessBeforeInitialization 和 postProcessAfterInitialization
// 兩個方法分別在 Bean 初始化之前和初始化之后得到執(zhí)行。注意,到這里 Bean 還沒初始化
registerBeanPostProcessors(beanFactory);
//初始化ApplicationContext的MessageSource
initMessageSource();
//初始化ApplicationContext事件廣播器
initApplicationEventMulticaster();
// 初始化子類特殊bean(鉤子方法)
onRefresh();
// 注冊事件監(jiān)聽器
registerListeners();
// 初始化所有singleton bean 重點(diǎn)!!重點(diǎn)!!
finishBeanFactoryInitialization(beanFactory);
// 廣播事件,ApplicationContext初始化完成
finishRefresh();
} catch (BeansException ex) {
....................
}

1. prepareRefresh()
??在rehresh之前做的準(zhǔn)備工作,一是設(shè)置spring啟動事件,開啟活躍狀態(tài);二是初始化屬性源信息;三是驗(yàn)證必要屬性。

1.1 initPropertySources()
??在應(yīng)用啟動之前替換一些屬性占位符,這個方法再Spring的對象中一般都沒有實(shí)現(xiàn),應(yīng)該是用來方便我們后期擴(kuò)展使用的方法。
1.2 validateRequiredProperties()
??Environment類的方法驗(yàn)證必須的屬性是否正確。
2. obtainFreshBeanFactory();
??獲取新的beanFactory,銷毀原有beanFactory、為每個bean生成BeanDefinition等
??obtainFreshBeanFactory方法從字面的意思看獲取新的Bean工廠,實(shí)際上這是一個過程,一個加載Xml資源并解析,根據(jù)解析結(jié)果組裝BeanDefinitions,然后初始化BeanFactory的過程。如下圖跳入方法源碼中

2.1 refreshBeanFactory()
??refreshBeanFactory是具體的刷新BeanFactory,負(fù)責(zé)這個工作做在類AbstractRefreshableApplicationContext中,顧名思義這是專門用來刷新的。

詳細(xì)說明:
- 首先判斷,是否存在
BeanFactory,如果存在容器beanFactory,則先銷毀所有的bean,然后關(guān)閉beanFactory; -
DefaultListableBeanFactory beanFactory = createBeanFactory();創(chuàng)建初始容器beanFactory,此處創(chuàng)建的是DefaultListableBaenFactory,是最重要的beanFactory,即初始化容器;spring注冊&加載bean的基本容器;
image -
customizeBeanFactory(beanFactory);根據(jù)AbstractRefreshableApplicationContext類的屬性為Beanfactory設(shè)置屬性值。
image
allowBeanDefinitionOverriding:屬性是指是否允對一個名字相同但definition不同進(jìn)行重新注冊,默認(rèn)是true。 allowCircularReferences屬性是指是否允許Bean之間循環(huán)引用,默認(rèn)是true
默認(rèn)兩個屬性都為空,可擴(kuò)展的,可以自己設(shè)置屬性,方法就是繼承ClassPathXmlApplicationContext并復(fù)寫customizeBeanFactory方法為兩個屬性設(shè)置值即可。 -
loadBeanDefinitions(beanFactory);將BeanDenifition注冊到bean工廠
[圖片上傳失敗...(image-e0509-1560845367203)]查看最后一個方法:
loadBeanDefinitions(beanDefinitionReader);
image
例如:applicationContext.xml不是在calsspath下了,只有Resource,那怎么辦,直接傳遞進(jìn)來即可,繼承ClassPathXmlApplicationContext類重寫getConfigResources方法,返回Resource即可。
3. prepareBeanFactory();
??在ApplicationContext刷新獲取beanFactory之后,開始準(zhǔn)備context使用的beanFactory。這一步相對比較簡單,就是配置beanFacotry的特性
-
beanFactory.setBeanClassLoader(getClassLoader());設(shè)置類加載器;設(shè)置BeanFactory的BeanClassLoader,如果存在,則直接使用之前的那個,否則,初始化一個新的ClassLoader;image beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));設(shè)置BeanExpressionResolver表達(dá)式解析器,主要用來解析EL表達(dá)式;Bean初始化完成后填充屬性時會用到beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));設(shè)置屬性注冊解析器PropertyEditor;這個主要是對某些注入的Bean的一些屬性的支持;beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor (this));此處添加了一個BeanPostProcessor實(shí)現(xiàn):ApplicationContextAwareProcessor,它是用來處理并回調(diào)實(shí)現(xiàn)了各種Aware接口的Bean,比如獲取ApplicationContext的ApplicationContextAware接口。添加BeanPostProcessor(Bean后置處理器ApplicationContextAwareProcessor),當(dāng)bean被這個工廠創(chuàng)建的時候會用到PostProcessor, 在beanfactory中存儲了beanPostProcessors的列表,在生效的時候,列表中的PostProcessor都會執(zhí)行。 在bean初始化之前,調(diào)用ApplicationContextAwareProcessor的postProcessBeforeInitialization處理所有的Aware接口,進(jìn)行如下操作:
// 如果bean實(shí)現(xiàn)了EmbeddedValueResolverAware接口,調(diào)用bean.setEmbeddedValueResolver
// 如果bean實(shí)現(xiàn)了ResourceLoaderAware接口,調(diào)用bean.setResourceLoader
// 如果bean實(shí)現(xiàn)了ApplicationEventPublisherAware接口,調(diào)用bean.setApplicationEventPublisher
// 如果bean實(shí)現(xiàn)了MessageSourceAware接口,調(diào)用bean.setMessageSource
// 如果bean實(shí)現(xiàn)了ApplicationContextAware接口,調(diào)用bean.setApplicationContext
-
beanFactory.ignoreDependencyInterface()指定的接口不會被自動注入進(jìn)去。 -
beanFactory.registerResolvableDependency()設(shè)置幾個自動裝配規(guī)則,例如BeanFactory則注入beanFactory ResourceLoader,ApplicationEventPublisher,ApplicationContext注入當(dāng)前對象
image -
beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)如果當(dāng)前BeanFactory包含loadTimeWeaverBean,說明存在類加載期織入AspectJ,則把當(dāng)前BeanFactory交給類加載期BeanPostProcessor實(shí)現(xiàn)類LoadTimeWeaverAwareProcessor來處理,從而實(shí)現(xiàn)類加載期織入AspectJ的目的。
image - 注冊當(dāng)前容器環(huán)境
environment組件Bean
[圖片上傳失敗...(image-edc8e7-1560845367203)] - 注冊系統(tǒng)配置
systemProperties組件Bean
image - 注冊系統(tǒng)環(huán)境
systemEnvironment組件Bean
image
??總結(jié):
(1)設(shè)置類加載器 (2)設(shè)置EL表達(dá)式解析器(bean創(chuàng)建完成填充屬性時使用)和屬性注冊解析器 (3)利用beanPostProcessor的特性給各種Aware接口的實(shí)現(xiàn)類注入ApplicationContext中對應(yīng)的屬性; (4)設(shè)置各種Aware接口的實(shí)現(xiàn)類為忽略自動裝配 (5)設(shè)置自動裝配類(BeanFactory,ResourceLoader,ApplicationEventPublisher,ApplicationContext) (6)如果BeanFactory中存在loadTimeWeaver的bean,那么需要添加動態(tài)織入功能 (7).注冊各種可用組件(environment,systemProperties,systemEnvironment)
4.postProcessBeanFactory()
??bean工廠的bean屬性處理容器,說通俗一些就是可以管理我們的bean工廠內(nèi)所有的beandefinition(未實(shí)例化)數(shù)據(jù);
??postProcessBeanFactory后處理beanFactory。時機(jī)是在所有的beanDenifition加載完成之后,bean實(shí)例化之前執(zhí)行。
??比如,在beanfactory加載完成所有的bean后,想修改其中某個bean的定義,或者對beanFactory做一些其他的配置,就可以用此方法。在系列文章中,可以實(shí)現(xiàn)ClassPathXmlApplicationContext類并重寫postProcessBeanFactory即可。
默認(rèn)情況下此方法是空的。需要子類去實(shí)現(xiàn)
注意:
BeanFactoryPostProcessor的主要作用是讓你能接觸到bean definitions,對bean definitions進(jìn)行一定hack,但是也僅此而已了。絕對不允許在BeanFactoryPostProcessor中觸發(fā)到bean的實(shí)例化!
舉例:
@Component
public class PrematureBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
Map<String, BBean> map = beanFactory.getBeansOfType(BBean.class);
for (BBean bBean : map.values()) {
assert bBean.getABean() == null;
}
}
}
@Component("bBean")
public class BBean {
@Autowired
private ABean aBean;
public ABean getABean() {
return aBean;
}
}
@Component
public class ABean {
private String name = "a";
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
??在運(yùn)行后,BBean中被期待注入的ABean最終為null。這是為啥呢?postProcessBeanFactory(beanFactory); 首先invoke了容器中的BeanFactoryPostProcessor實(shí)現(xiàn)類,其中當(dāng)然就包括PrematureBeanFactoryPostProcessor,此時通過beanFactory.getBeansOfType觸發(fā)了bean提前實(shí)例化。按理說,bean提前實(shí)例化也應(yīng)該沒問題的,aBean也應(yīng)該是能夠被注入的呀!那為啥最終不是這個結(jié)果呢?
??從源碼可知:
@AutoWired起作用依賴AutowiredAnnotationBeanPostProcessor;
@Resource依賴CommonAnnotationBeanPostProcessor,這倆都是BeanPostProcessor的實(shí)現(xiàn)。
??那BeanPostProcessors在何處被spring invoke呢?
參見refresh()方法registerBeanPostProcessors(beanFactory);
在postProcessBeanFactory(beanFactory);后面被調(diào)用;
??也就是說BBean被觸發(fā)提前初始化的時候,AutowiredAnnotationBeanPostProcessor還沒有被注冊自然也不會被執(zhí)行到,自然ABean=null。
5.invokeBeanFactoryPostProcessors(beanFactory);
??實(shí)例化Factory之前預(yù)處理部分
??invokeBeanFactoryPostProcessors 方法主要用于處理 BeanFactoryPostProcessor 接口。BeanFactoryPostProcessor 接口是 Spring 初始化 Bean 時對外暴露的擴(kuò)展點(diǎn),Spring IoC 容器允許 BeanFactoryPostProcessor 在容器實(shí)例化任何 Bean 之前讀取Bean 的定義,并可以修改它。
??可以理解為,初始化我們自定義的BeanFactoryPostProcessor;
postProcessBeanFactory用于在標(biāo)準(zhǔn)的初始化完成后修改容器上下文中的beanFactory。所有bean定義將被加載,但是它們將暫時不被實(shí)例化,這允許覆蓋,甚至添加一些屬性到延遲初始化的bean上。也就是說,允許我們開發(fā)者自定義的去修改BeanFactory中的內(nèi)容,這也是符合“spring”的開閉原則。invokeBeanFactoryPostProcessors,就是調(diào)用postProcessBeanFactory。

5.1. getBeanFactoryPostProcessors()
??獲取的手動注冊的BeanFactoryPostProcessor;
??是通過beanFactory.addBeanPostProcessor()方法設(shè)置的BeanFactoryPostProcessor。默認(rèn)空的,因?yàn)闆]有通過addBeanFactoryPostProcessor方法添加BeanFactoryPostProcessor

5.2 PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors()
未完待續(xù)...
6. registerBeanPostProcessors(beanFactory);
注冊BeanPostProcessor
String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);


注冊BeanPostProcessor和invokeBeanFactoryPostProcessors很像,并且沒什么復(fù)雜邏輯。就是將已經(jīng)注冊到beanFacory的Bean篩選出BeanPostProcessor然后添加到ApplicationContext的beanPostProcessor集合中。
主要邏輯:
:首先在容器中注冊一個
BeanPostProcessorChecker,這個只是用來對在bean不適合所有的BeanPostProcessor調(diào)用的情況下,打印一些日志信息。:先注冊實(shí)現(xiàn)了
PriorityOrdered接口的BeanPostProcessor,再注冊實(shí)現(xiàn)了Ordered接口的的BeanPostProcessor,然后注冊什么接口都沒實(shí)現(xiàn)的BeanPostProcessor,最后注冊實(shí)現(xiàn)了MergedBeanDefinitionPostProcessor接口的BeanPostProcessor。:注冊
ApplicationListenerDetector。用來檢測bean是否是ApplicationListener,如果是判斷是否是單例,如果不是單例,那么刪除singtonNames中對應(yīng)的key。
7. initMessageSource();初始化消息源
為本context初始化消息源;
判斷beanFactory中是否有名字為messageSource的bean,如果有,從beanFactory中獲取并且判斷獲取的是不是HierarchicalMessageSource類型的,如果是設(shè)置其父級消息源;如果沒有,新建DelegatingMessageSource類作為messageSource的Bean。

8. initApplicationEventMulticaster();初始化應(yīng)用事件廣播器
初始化ApplicationEventMulticaster,
首先判斷beanFactory容器中是否存在這個廣播器:applicationEventMulticaster;
如果存在,則用beanFactory中的bean;如果不存在則使用新建SimpleApplicationEventMulticaster

9. onRefresh();
10. registerListeners();注冊監(jiān)聽器
在發(fā)布事件的時候會從這里注冊的監(jiān)聽器中去獲??;

11.finishBeanFactoryInitialization(beanFactory);
完成此上下文的 bean 工廠的初始化,初始化所有剩余的單例 bean。實(shí)例化所有的非懶加載單例。是ApplicationContext刷新的時候,最重要的方法了,因?yàn)樗械腷ean,如果不是lazy-init的都會在這一步進(jìn)行實(shí)例化,并且做一些處理。

12.finishRefresh();
完成對context的刷新
13.總結(jié)
1.prepareRefresh();對刷新進(jìn)行準(zhǔn)備,包括設(shè)置開始時間,設(shè)置激活狀態(tài),初始化Context中的占位符,子類根據(jù)其需求執(zhí)行具體準(zhǔn)備工作,而后再由父類驗(yàn)證必要參數(shù)
2.obtianFreshBeanFactory();,刷新并獲取內(nèi)部的BeanFactory對象
3.prepareBeanFactory(beanFactory);,對BeanFactory進(jìn)行準(zhǔn)備工作,包括設(shè)置類加載器和后置處理器,配置不能自動裝配的類型,注冊默認(rèn)的環(huán)境Bean
4.postProcessBeanFactory(beanFactory);為Context的子類提供后置處理BeanFactory的擴(kuò)展能力,如想在bean定義加載完成后,開始初始化上下文之前進(jìn)行邏輯操作,可重寫這個方法
5.invokeBeanFactoryPostProcessors(beanFactory);,執(zhí)行Context中注冊的BeanFactory后置處理器,有兩張?zhí)幚砥?一種是可以注冊Bean的后置處理器,一種的針對BeanFactory的后置處理器,執(zhí)行順序是先按優(yōu)先級執(zhí)行注冊Bean的后置處理器,而后再按優(yōu)先級執(zhí)行針對BeanFactory的后置處理器
SpringBoot中會進(jìn)行注解Bean的解析,由ConfigurationClassPostProcessor觸發(fā),由ClassPathDefinitionScanner解析,并注冊到BeanFactory
6.registerBeanFactoryProcessor(beanFactory();,按優(yōu)先級順序在BeanFactory中注冊Bean的后置處理器,Bean處理器可在Bean的初始化前后處理
7.initMessageSource();初始化消息源,消息源用于支持消息的國際化
8.initApplicationEventMuticaster();初始化應(yīng)用事件廣播器,用于向ApplicationListener通知各種應(yīng)用產(chǎn)生的事件,標(biāo)準(zhǔn)的觀察者模型
9.onRefresh();,用于子類的擴(kuò)展步驟,用于特定的Context子類初始化其他的Bean
10.registerListeners();,把實(shí)現(xiàn)了ApplicationListener的類注冊到廣播器,并對廣播其中早期沒有廣播的事件進(jìn)行通知
11.finishBeanFactoryInitialization(beanFactory);,凍結(jié)所有Bean描述信息的修改,實(shí)例化非延遲加載的單例Bean
12.finishRefresh();,完成上下文的刷新工作,調(diào)用LifecycleProcessor.onRefresh(),以及發(fā)布







