【原創文章,轉載請注明出處】【本文地址】http://www.cnblogs.com/zffenger/p/5813470.html
在使用Spring的時候,我們經常需要先得到一個ApplicationContext對象,然后從該對象中獲取我們配置的Bean對象。ApplicationContext隸屬於org.springframework.context,是SpringFramework中Bean的管理者,為SpringFramework的諸多功能提供支撐作用。
下圖是Spring-4.3.2.RELEASE版本中ApplicationContext相關的UML類視圖(淺綠色的為接口,淺黃色的為類):
BeanFactory系列接口:
public interface BeanFactory
BeanFactory 是 Spring 管理 Bean 的最頂層接口,是一個 Bean 容器, 管理一系列的 bean,每一個 bean 使用一個String 類型的 name(或稱之為id) 來唯一確定,這些 Bean 可以是 prototype 的或者 singleton的 。Spring 提倡使用依賴注入(Dependency Injection) 的方式裝配 Bean。BeanFactory從“configuration source”加載Bean的定義,configuration source 可以是xml文件或者properties文件甚至是數據庫。
public interface HierarchicalBeanFactory extends BeanFactory
BeanFactory的子接口HierarchicalBeanFactory是一個具有層級關系的Bean 工廠,擁有屬性parentBeanFactory。當獲取 Bean對象時,如果當前BeanFactory中不存在對應的bean,則會訪問其直接 parentBeanFactory 以嘗試獲取bean 對象。此外,還可以在當前的 BeanFactory 中 override 父級BeanFactory的同名bean。
public interface ListableBeanFactory extends BeanFactory
ListableBeanFactory 繼承了BeanFactory,實現了枚舉方法可以列舉出當前BeanFactory中所有的bean對象而不必根據name一個一個的獲取。 如果 ListableBeanFactory 對象還是一個HierarchicalBeanFactory則getBeanDefinitionNames()方法只會返回當前BeanFactory中的Bean對象而不會去父級BeanFactory中查詢。
其他接口:
public interface PropertyResolver
配置文件解析器的最頂級接口,解析配置文件獲取屬性值等作用
public interface Environment extends PropertyResolver
提供當前Application運行的所需環境
public interface EnvironmentCapable
這是一個Environment Holder,只有一個方法:Environment getEnvironment() 用來獲取Environment對象
public interface ApplicationEventPublisher
該接口的功能是publish Event,向事件監聽器(Listener)發送事件消息
public interface MessageSource
解析message的策略接口,方法形如: String getMessage(String, Object[], String, Locale),用於支撐國際化等功能
public interface ResourcePatternResolver extends ResourceLoader
其中ResourceLoader用於從一個源(如InputStream等)加載資源文件,ResourcePatternResolver 是ResourceLoader的子類,根據 path-pattern 加載資源。
ApplicationContext接口:
public interface ApplicationContext extends EnvironmentCapable, ListableBeanFactory, HierarchicalBeanFactory, MessageSource, ApplicationEventPublisher, ResourcePatternResolver
重點來了,ApplicationContext接口繼承眾多接口,集眾多接口功能與一身,為Spring的運行提供基本的功能支撐。根據程序設計的“單一職責原則”,其實每個較頂層接口都是“單一職責的”,只提供某一方面的功能,而ApplicationContext接口繼承了眾多接口,相當於擁有了眾多接口的功能,下面看看它的主要功能:
- 首先,它是個BeanFactory,可以管理、裝配bean,可以有父級BeanFactory實現Bean的層級管理(具體到這里來說它可以有父級的ApplicationContext,因為ApplicationContext本身就是一個BeanFactory。這在web項目中很有用,可以使每個Servlet具有其獨立的context, 所有Servlet共享一個父級的context),它還是Listable的,可以枚舉出所管理的bean對象。
- 其次,它是一個ResourceLoader,可以加載資源文件;
- 再次,它可以管理一些Message實現國際化等功能;
- 還有,它可以發布事件給注冊的Listener,實現監聽機制。
ApplicationContext 的子接口:
ApplicationContext 接口具有兩個直接子接口,分別是:
org.springframework.context.ConfigurableApplicationContext
org.springframework.web.context.WebApplicationContext
分別看這兩個子接口:
public interface ConfigurableApplicationContext extends ApplicationContext, Lifecycle, Closeable
根據接口名可以判決,該接口是可配置的!ApplicationContext 接口本身是 read-only 的,所以子接口 ConfigurableApplicationContext 就提供了如setID()、setParent()、setEnvironment()等方法,用來配置ApplicationContext。
再看其繼承的另外兩個接口:
- Lifecycle:Lifecycle接口中具有start()、stop()等方法,用於對context生命周期的管理;
- Closeable:Closeable是標准JDK所提供的一個接口,用於最后關閉組件釋放資源等;
public interface WebApplicationContext extends ApplicationContext
該接口僅僅在原接口基礎上提供了getServletContext(),用於給servlet提供上下文信息。
public interface ConfigurableWebApplicationContext extends WebApplicationContext, ConfigurableApplicationContext
這里 ConfigurableWebApplicationContext 又將上述兩個接口結合起來,提供了一個可配置、可管理、可關閉的WebApplicationContext,同時該接口還增加了setServletContext(),setServletConfig()等set方法,用於裝配WebApplicationContext。
到這里ApplicationContext相關接口基本上已經講完了,總結起來就兩大接口:
org.springframework.context.ConfigurableApplicationContext
org.springframework.web.context.ConfigurableWebApplicationContext
對於普通應用,使用ConfigurableApplicationContext 接口的實現類作為bean的管理者,對於web應用,使用ConfigurableWebApplicationContext 接口的實現類作為bean的管理者。這兩個接口,從結構上講他們是繼承關系,從應用上講他們是平級關系,在不同的領域為Spring提供強大的支撐。
ApplicationContext相關實現類設計:
Spring是一個優秀的框架,具有良好的結構設計和接口抽象,它的每一個接口都是其功能具體到各個模塊中的高度抽象,實際使用過程中相當於把接口的各個實現類按照接口所提供的組織架構裝配起來以提供完整的服務,可以說掌握了Spring的接口就相當於掌握了Spring的大部分功能。
ApplicationContext 的實現類眾多,然而
上文中分析了 ApplicationContext 接口的各個功能,下面將分析 ApplicationContext 的實現類對上述接口的各個功能都是怎樣實現的(PS. 限於篇幅,這里僅僅指出上述各個功能在實現類中什么位置通過什么方法實現,至於其具體實現過程,每一個功能拿出來都可以單獨寫一篇文章了,這里不進行詳述)。至於實現類又擴展了其他接口或者繼承了其他父類,這些只是實現類為了擴展功能或者為了對實現上述接口提供便利而做的事情,對ApplicationContext接口抽象出來的功能沒有影響或者沒有太大幫助,因此略去。
以ClassPathXmlApplicationContext為例,其主要繼承關系如下:
org.springframework.context.support.AbstractApplicationContext
org.springframework.context.support.AbstractRefreshableApplicationContext
org.springframework.context.support.AbstractRefreshableConfigApplicationContext
org.springframework.context.support.AbstractXmlApplicationContext
org.springframework.context.support.ClassPathXmlApplicationContext
而最頂層抽象類 AbstractApplicationContext 又實現了 ConfigurableApplicationContext 接口。
AbstractApplicationContext extends DefaultResourceLoader implements ConfigurableApplicationContext, DisposableBean
根據上文所述,這里略去其父類 DefaultResourceLoader 和接口 DisposableBean ,只關注接口 ConfigurableApplicationContext,回憶一下該的主要功能:
Configable, //可配置(該接口本身擴展的功能) Lifecycle, //生命周期可管理 Closeable,//可關閉(釋放資源) EnvironmentCapable,//可配置Environment MessageSource, //可管理message實現國際化等功能 ApplicationEventPublisher, //可publish事件,調用Listener ResourcePatternResolver,//加載pattern指定的資源 ListableBeanFactory, HierarchicalBeanFactory,//管理Bean的生命周期,這個最重要,放最后說
然后回到最頂層抽象類 AbstractApplicationContext ,該抽象類可以說是 ClassPathXmlApplicationContext 繼承結構中代碼量最多的類,上述的大部分功能也都在該類中實現。該類采用模板方法模式,實現了上述功能的大部分邏輯,然后又抽出許多 protected方法(或 abstract 方法)供子類override 。
各功能的實現列舉如下:
Configable:如setParent/setEnvironment等方法,由AbstractApplicationContext實現 。代碼示例:
@Override public void setParent(ApplicationContext parent) { this.parent = parent; if (parent != null) { Environment parentEnvironment = parent.getEnvironment(); if (parentEnvironment instanceof ConfigurableEnvironment) { getEnvironment().merge((ConfigurableEnvironment) parentEnvironment); } } }
Lifecycle:AbstractApplicationContext擁有一個LifecycleProcessor實例,用於管理自身的生命周期,AbstractApplicationContext的Lifecycle方法如start、stop等由會代理給LifecycleProcessor進行處理,代碼示例:
@Override public void start() { getLifecycleProcessor().start(); publishEvent(new ContextStartedEvent(this)); }
Closeable:由AbstractApplicationContext實現,用於關閉ApplicationContext銷毀所有beans,此外如果注冊有JVM shutdown hook,同樣要將其移除 。代碼示例:
@Override public void close() { synchronized (this.startupShutdownMonitor) { doClose(); if (this.shutdownHook != null) { try { Runtime.getRuntime().removeShutdownHook(this.shutdownHook); }catch (IllegalStateException ex) { // ignore - VM is already shutting down } } } }
EnvironmentCapable:由AbstractApplicationContext實現,其持有一個ConfigurableEnvironment實例,用來實現EnvironmentCapable接口的getEnvironment方法 。代碼示例:
@Override public ConfigurableEnvironment getEnvironment() { if (this.environment == null) { this.environment = createEnvironment(); } return this.environment; }
MessageSource:AbstractApplicationContext持有一個MessageSource實例,將MessageSource接口的方法代理給該實例來完成 。代碼示例:
@Override public String getMessage(String code, Object args[], String defaultMessage, Locale locale) { return getMessageSource().getMessage(code, args, defaultMessage, locale); }
ApplicationEventPublisher:由AbstractApplicationContext實現,如果存在父級ApplicationContext,則同樣要將event發布給父級ApplicationContext。代碼示例:
@Override public void publishEvent(ApplicationEvent event) { Assert.notNull(event, "Event must not be null"); if (logger.isTraceEnabled()) { logger.trace("Publishing event in " + getDisplayName() + ": " + event); } getApplicationEventMulticaster().multicastEvent(event); if (this.parent != null) { this.parent.publishEvent(event); } }
ResourcePatternResolver:AbstractApplicationContext持有一個ResourcePatternResolver實例,該接口的方法代理給該實例完成 。代碼示例:
@Override public Resource[] getResources(String locationPattern) throws IOException { return this.resourcePatternResolver.getResources(locationPattern); }
ListableBeanFactory, HierarchicalBeanFactory: AbstractApplicationContext 間接實現了這兩個接口,然而卻並沒有實現任何BeanFactory的任何功能。AbstractApplicationContext 擁有一個 ConfigurableListableBeanFactory實例,所有BeanFactory的功能都代理給該實例完成。代碼示例:
@Override public Object getBean(String name) throws BeansException { assertBeanFactoryActive(); return getBeanFactory().getBean(name); }
而AbstractApplicationContext 的 getBeanFactory() 方法是一個抽象方法,即由子類來提供這個BeanFactory。代碼示例:
@Override public abstract ConfigurableListableBeanFactory getBeanFactory() throws IllegalStateException;
在 ClassPathXmlApplicationContext 的繼承體系中,類AbstractRefreshableApplicationContext實現了這個 getBeanFactory()方法。這里getBeanFactory()方法會創建一個DefaultListableBeanFactory實例作為返回值。
小結
本文以 Spring Framework 的 ApplicationContext 為中心,分析了 ApplicationContext 的機構體系和功能實現。接口 ApplicationContext 繼承了眾多接口,可以滿足應用中“面向接口編程”的常用功能需求。抽象類 AbstractApplicationContext 實現了ApplicationContext 接口中簡單不易變動的部分,然后通過“組合”將眾多“容易變動”功能代理給它的一些成員變量來實現,最后再使用模板方法模式讓子類為父類提供一些函數的支持或者設置替換父類的上述成員變量,從而實現了“對擴展開放,對修改封閉”的設計原則,為Spring Framework 提供了靈活性大可擴展性強的架構支撐。
【原創文章,轉載請注明出處】【本文地址】http://www.cnblogs.com/zffenger/p/5813470.html