天天看點

(轉) Spring源碼閱讀 之 Spring整體架構

标簽(空格分隔): Spring

聲明:本文系轉載,原地位址: spring framework 4 源碼閱讀

Spring骨架

Spring的骨架,也是Spring的核心包。主要包含三個内容

  1. context:spring的上下文 ---> 導演(個人覺得其實稱為 舞台更合适)
  2. core:spring的核心包,主要包括spring所有用到的工具 ---> 道具
  3. beans:spring的bean執行個體 ---> 演員
(轉) Spring源碼閱讀 之 Spring整體架構

導演負責安排演出,演員負責按照導演的訓示來演出,演出過程中需要使用道具。我想大家看完這些圖檔之後就明白大緻的包關系了。

Spring包結構

(轉) Spring源碼閱讀 之 Spring整體架構

大家看到相應包内容:

  • core包側重于工具類。
  • beans包更側重于bean執行個體的描述。
  • context更側重于全局控制,功能衍生。

    下面我們就針對于context和factory類的關系繼續一個基本概況:

核心類之前的關系

我們先來看下bean包下的beanfactory類 以及抽象類等。

(轉) Spring源碼閱讀 之 Spring整體架構

可以看到在接口的實作泛化的過程中,每一個接口在繼承父接口的同時,也繼承了父接口的一些方法。這就可以看出面向接口的微妙之處。

BeanFactory(所有BeanFactory的父類)

(轉) Spring源碼閱讀 之 Spring整體架構

可以看到beanFactory中定義了一些基本方法,包括根據名稱擷取bean執行個體等。

HierarchicalBeanFactory(階層化的BeanFactory)

(轉) Spring源碼閱讀 之 Spring整體架構

可以看到此接口實作了階層化,及擷取beanFactory的父容器。

ListableBeanFactory(清單式BeanFactory)

(轉) Spring源碼閱讀 之 Spring整體架構

可以看到為beanfactory設定了清單的功能,并且規劃了如何從清單中取出相應的方法的能力。

小結

從上述類命名以及接口規劃可以看到,通過接口的不斷繼承,beanfactory被不斷的豐富抽象起來。層層細分之後,每個類的職責都變的非常單一了,同時在擴充起來也更加友善了。針對源代碼,最好的辦法還是根據名稱來,最友善。

context(上下文)

(轉) Spring源碼閱讀 之 Spring整體架構

可以看到context的初始化不同于beanfactory,可以側重于抽象類型,具體的方法實作。

裡面大部分方法使用了模闆方法設計模式,父類調用抽象方法,抽象方法在子類中實作,對象的獨立性。

主要分成三種context:XML Annotation Groovy 三種形式。

registry(執行個體或者bean描述注冊器)

(轉) Spring源碼閱讀 之 Spring整體架構

将初始化完成的bean注冊到容器中,針對于單例部分,緩存單例執行個體。針對beanDefinition部分,緩存bean的描述。

Strategy(初始化政策)

(轉) Spring源碼閱讀 之 Spring整體架構

兩種初始化政策:一種是簡單政策,一種是cglib的政策,這裡使用的模式是政策模式。

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)

(轉) Spring源碼閱讀 之 Spring整體架構