spring framework 4 原始碼閱讀
阿新 • • 發佈:2019-02-15
前面寫了幾篇spring 的介紹文章,感覺與主題不是很切合。重新整理下思路,從更容易理解的角度來寫下文章。
spring 的骨架
spring 的骨架,也是spring 的核心包。主要包含三個內容 1.context:spring 的上線文-------導演 2.core:spring的核心包,主要包括spring所以用到的工具-------道具 3.beans:spring的bean例項 -------演員導演負責安排演出,演員負責按照導演的指示來演出,演出過程中需要使用道具。
我想大家看完這些圖片之後就明白大致的包關係了。
spring包結構
大家看到相應包內容。 core包側重於幫助類,操作工具,beans包更側重於bean例項的描述。context更側重全域性控制,功能衍生。 下面我們就針對context和factory對類的關係繼續一個基本概括:
核心類之間的關係
可以看到在介面的實現泛化的過程中,每一個介面在繼承父介面的同時,也繼承了父介面的一些方法。這就可以看出面向介面變成微妙之處。
BeanFactory【所有BeanFactory的父類】
可以看到beanfactory中定義了一些基本方法,包括根據名稱獲取bean例項等。
HierarchicalBeanFactory【層次化的BeanFactory】
可以看到此介面實現了層次化,及獲取beanFactory的父容器
LisableBeanFactory列表式Beanfactory
可以看到為beanfactory設定了列表的功能,並且規劃瞭如何從列表中取出相應的方法的能力。
小結:
context【上下線文】
可以看到到了context的初始化不同於beanfactory,可以側重於抽象型別,具體的方法實現。 裡面大部分方法使用了模板方法的設計模式,父類呼叫抽象方法,抽象方法在子類中實現,物件的獨立性。 主要分成三種context:XML,Annotation,Groovy針對三種形式。
registry【例項或者bean描述註冊器】
將初始化完成的bean註冊的容器中,針對單例來部分,快取單例例項。針對beanDefinition部分,快取bean描述。
Strategy【初始化策略】
兩種初始化策略 一種是簡單策略,一種是cgilib的策略,當時這裡使用的模式是策略模式。
context的初始化
/**
* 在parent下建立ClassPathXmlApplicaitonContext,
* 從XML中讀取所有Bean定義.
* @param configLocations 配置檔案路徑如c:\simpleContext.xml
* @param refresh 是否需要自動重新整理context,refresh-->重新載入
* 載入所有的bean定義,建立所有單例.
* refresh為true的時候, 根據context來手工重新整理
* @param parent the parent context
* @throws BeansException if context creation failed
* @see #refresh()
*/
public ClassPathXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent)
throws BeansException {
//初始化XmlApplicationContext
super(parent);
//轉換配置檔案的路徑
setConfigLocations(configLocations);
if (refresh) {
//重新重新整理原有的context,這一篇的重點
refresh();
}
}
下面我們來看下AbstractApplicationContext.refresh()方法
//載入或重新整理持久的配置,可能是xml檔案,properties檔案,或者關係型資料庫的概要。
//做為一個啟動方法,如果初始化失敗將會銷燬已經建立好的單例,避免重複載入配置檔案。
//換句話說,在執行這個方法之後,要不全部載入單例,要不都不載入
public void refresh() throws BeansException, IllegalStateException
{
synchronized (this.startupShutdownMonitor)
{
// 初始化配置準備重新整理,驗證環境變數中的一些必選引數
prepareRefresh();
// 告訴繼承類銷燬內部的factory建立新的factory的例項
// 初始化Bean例項
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// 初始化beanFactroy的基本資訊,包括classloader,environment,忽略的註解等
prepareBeanFactory(beanFactory);
try {
// beanfactory內部的postProcess,可以理解為context中PostProcess的補充
beanFactory.postProcessBeanFactory(beanFactory);
// 執行BeanFactoryPostProcessor(在beanFactory初始化過程中,bean初始化之前,修改beanfactory引數)、
// BeanDefinitionRegistryPostProcessor 其實也是繼承自BeanFactoryPostProcessor,
// 多了對BeanDefinitionRegistry的支援invokeBeanFactoryPostProcessors(beanFactory);
// 執行postProcess,那BeanPostProcessor是什麼呢,是為了在bean載入過程中修改bean的內容,
// 使用分的有兩個而方法Before、After分別對應初始化前和初始化後
registerBeanPostProcessors(beanFactory);
// 初始化MessageSource,主要用作I18N本地化的內容
initMessageSource();
// 初始化事件廣播ApplicationEventMulticaster,使用觀察者模式,對註冊的ApplicationEvent時間進行捕捉
initApplicationEventMulticaster();
// 初始化特殊bean的方法
onRefresh();
// 將所有ApplicationEventListener註冊到ApplicationEventMulticaster中
registerListeners();
// 初始化所有不為lazy-init的bean,singleton例項
finishBeanFactoryInitialization(beanFactory);
// 初始化lifecycle的bean並啟動(例如quartz的定時器等),如果開啟JMX則將ApplicationContext註冊到上面
finishRefresh();
}
catch (BeansException ex)
{
//銷燬已經建立單例
resources.destroyBeans();
// 將context的狀態轉換為無效,標示初始化失敗
flag.cancelRefresh(ex);
// 將異常傳播到呼叫者
throw ex;
}
}
}
我們從時序圖來看啟動上述初始化(門面模式facade)