理解Spring 容器設計理念
概述
Spring是為了解決企業應用程式開發複雜性而建立的開源框架,書店上關於Spring的書籍汗牛充棟,網上相關的文章連篇累牘,其中有很多寫的很不錯的,有入門例子的,有問題解決方案的,有環境設定的,有原始碼分析的,有spring與其他開源系統整合的,不一而足。本文通過生活白話,不拘泥於Spring原始碼和專業術語的束縛,不拘泥於具體的實現細節,類比介紹Spring容器的巨集觀的設計理念。
Spring容器解說
Spring容器提供 Spring 框架的基本功能,是工廠模式的實現。換句話說,Spring就是Bean的工廠,管理Bean的生命週期。那如何來設計呢?Spring原始碼雖不說是浩如煙海,也讓人頭暈目眩,如下圖所示,我們讓Spring容器走下神壇,既然是面向介面程式設計,用介面來描述框架,不必拘泥於具體實現可能更清晰些。
任何的設計都是這樣,有原料,有入口,有加工,也有出口。既然Spring是Bean的容器,是Bean的工廠,那麼生產Bean流程是:
1) 原料:bean的配置檔案
2) 進料:通過ResourceLoader把xml文字檔案讀入
3) 初加工:通過BeanDefinitionReader把原料加工成半成品BeanDefinition
4) 精加工:Bean的生產車間BeanFactory把半成品BeanDefinition加工成Bean
5) 入庫:成品庫SingletonRegistry儲存成品Bean,及Bean的標籤(
IOC是Sprng 核心?關鍵?
Spring容器使用控制反轉 (IOC) 模式將應用程式的配置和依賴性規範與實際的應用程式程式碼分開,控制反轉(IOC)模式是基於java反射的基本原理。
通常的軟體設計,肯定把IOC作為容器的核心,其他外圍的功能如bean 的Scope都是基於IOC展開,而Spring設計卻只把它放如工具類BeanUtil,這正是Spring的高明之處,雖然IOC是Spring的建立bean的基礎,但建立一個bean需要判斷是否靜態工廠建立,是否有含引數的構造方法,而這些引數也可能是其他物件的例項,建立bean的初始化方法等等,這些不僅僅是bean的IOC所能涵蓋的,並且在建立一個bean的過程中可能需要多次迭代呼叫IOC程式。
綜上所述,IOC雖然是Spring的建立Bean的基本原理,但僅是及其重要的一部分,並不是Spring容器的核心,是Spring建立bean的比不可少的工具。IOC是Spring容器的關鍵,而不是核心。
Interface分級設計
介面的分級設計,是針對不同的客戶給予不同級別的產品。不同等級的介面關注點也各有不同,就像產品也分為多個級別,如高階產品、中級產品、初級產品分別對應於不同的客戶群,或者如同銀行的客戶渠道有銀行卡,櫃檯,網銀,手機終端,ATM機等等。同樣介面也分為內部介面和外部介面,就如同有些介面可能永遠不被外部使用者所知,僅僅是內部使用,就像工廠內部多個車間之間的內部產品。
org.springframework.beans.factory. BeanFactory是Spring的頂級Interface,其中只有getBean系列,containsBean,isPrototype,isSingleton,getType等成品Bean的基本方法。
org.springframework.beans.factory. ListableBeanFactory是Factory的管理方法如containsBeanDefinition,getBeanDefinitionCount,getBeanDefinitionNames,getBeanNamesForType系列,getBeansOfType系列,ListableBeanFactory是針對BeanDefinition半成品的。
而ApplicationContext介面除了整合ListableBeanFactory介面外,還繼承了ResourcePatternResolver,HierarchicalBeanFactory,ApplicationEventPublisher,MessageSource的功能,如在資源處理(國際化處理),事件傳遞,及各應用層之間的context實現。同樣是對外的介面,Spring更建議採用ApplicationContext的原因也就在這兒,ApplicationContext更像是針對VIP客戶的產品。
Interface擴充套件設計
Spring設計是開放性的設計思路,是值得我們做架構設計人員學習的,如下圖所示:
com.springframework.beans.factory (淡黃色背景) |
|BeanFactory |ListableBeanFactory |ConfigrableListableBeanFactory |DefaultListableBeanFactory |
|
com.springframework.context (棕紅色背景) |
ApplicationContext ConfigrableApplicationContext |
|
org.springframework.context (黃色背景) |
.support |
AbstractApplicationContext AbstractRefreshableApplicationContext AbstractXmlApplicationContext ClassPathXmlApplicationContext |
org.springframework.web.context (綠色背景) |
WebApplicationContext ConfigrableWebApplicationContext |
|
org.springframework.web.context (淺藍色背景) |
.support |
AbstractRefreshableWebApplicationContext XmlWebApplicationContext |
總結如下:
1) 不同的包下面放不同的東西,好像是廢話啊!上層包放介面,下層包放實現的抽象類及實體類。如contex.support包下面放實現context包下面的介面的抽象類及實現類。
2) 為了適應WEB級別的ApplicationContext,建立了WebApplicationContext的介面,該介面繼承了ApplicationContext,又添加了WEB層的個性化方法如getServletContext及屬性。現在終於明白了在介面間的“extends”的含義,絕對是對上層介面的“擴充套件“,擴充套件的目的是適應更具體化的環境。就如同因為國家大,情況複雜,中央的政策相對都是比較抽象的,而地方政策必須結合地方的特色,既要滿足中央政策的要求,即實現中央政策的介面,又要根據本地特殊情況,擴充套件個性化的政策,即地方政策介面,從而更具有可操作性。
3) 在org.springframework.web.context.support.AbstractRefreshableWebAppplicationContext類是既實現了ConfigrableWebApplicationContext介面,即實現WEB的個性化特色,又繼承了org.springframework.context.support.AbstractRefreshableApplicationContext類。藉助了已有的類,實現了架構上的複用,這就像制定政策既要滿足地方上的特色,又可以參照其他地區現成的政策經驗。呵呵!在實際工作中,也會常常有這樣的設計。