【Spring源碼分析系列】ApplicationContext 相關接口架構分析

在使用Spring的時候,咱們常常須要先獲得一個ApplicationContext對象,而後從該對象中獲取咱們配置的Bean對象。ApplicationContext隸屬於org.springframework.context,是SpringFramework中Bean的管理者,爲SpringFramework的諸多功能提供支撐做用。web

下圖是Spring-4.3.2.RELEASE版本中ApplicationContext相關的UML類視圖(淺綠色的爲接口,淺黃色的爲類):spring

SpringApplicationContext

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運行的所需環境ide

public interface EnvironmentCapable

這是一個Environment Holder,只有一個方法:Environment getEnvironment() 用來獲取Environment對象函數

public interface ApplicationEventPublisher

該接口的功能是publish Event,向事件監聽器(Listener)發送事件消息this

public interface MessageSource

解析message的策略接口,方法形如: String getMessage(String, Object[], String, Locale),用於支撐國際化等功能spa

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 提供了靈活性大可擴展性強的架構支撐。

相關文章
相關標籤/搜索