spring源碼分析之context

重點類:html

一、ApplicationContext是核心接口,它爲一個應用提供了環境配置。當應用在運行時ApplicationContext是隻讀的,但你能夠在該接口的實現中來支持reload功能。java

定義web

public interface ApplicationContext extends EnvironmentCapable, ListableBeanFactory, HierarchicalBeanFactory,
        MessageSource, ApplicationEventPublisher, ResourcePatternResolver {
}

特色:spring

提供了一個bean工廠方法來訪問應用組件,經過繼承org.springframework.beans.factory.ListableBeanFactory來得到的;數組

經過通用的方式來加載文件資源的能力,經過繼承org.springframework.core.io.ResourceLoader來得到的;app

發佈事件到註冊的監聽器的能力,經過繼承ApplicationEventPublisher來得到的;異步

解析消息,支持國際化的能力,經過繼承MessageSource來得到的;編輯器

context的繼承機制。定義在子context將優先級別更高。這意味着,例如:一個父context能夠被整個web應用共享,而每一個servlet能夠有本身的子context,而且這些servlet彼此獨立。例如http://www.cnblogs.com/davidwang456/p/4122842.htmlide

另外還有標準的org.springframework.beans.factory.BeanFactory的生命週期管理能力,ApplicationContext實現類發現和觸發beanApplicationContextAware,還包括ResourceLoaderAware,ApplicationEventPublisherAware,MessageSourceAware bean。工具

1.1 EnvironmentCapable

包含並暴露了Environment引用的接口。定義

public interface EnvironmentCapable {

    /**
     * Return the {@link Environment} associated with this component.
     */
    Environment getEnvironment();

}

其中,Environment表示當前運行的應用所在的環境,它有兩個重要的熟悉:profiles和properties。

proportiers相關方法經過父接口PropertyResolver來暴露。

profile用來爲註冊的bean進行邏輯分組的工具,例如開發環境,測試環境,發佈環境等。profile的激活能夠經過設置AbstractEnvironment#ACTIVE_PROFILES_PROPERTY_NAME"spring.profiles.active"的系統

屬性,也能夠經過調用ConfigurableEnvironment的setActiveProfiles(String...)來激活。

1.2 ListableBeanFactory

ListableBeanFactory能夠枚舉全部bean的實例。注意,若該Beanfactory是HierarchicalBeanFactory,那麼將不會考慮BeanFactory的繼承關係,只返回當前工廠定義的相關bean。可使用BeanFactoryUtils工具類獲取父beanfactory的bean。

1.3 HierarchicalBeanFactory

HierarchicalBeanFactory能夠經過方法BeanFactory getParentBeanFactory()獲取父BeanFactory,其子接口定義了設置父BeanFactory的方法:void setParentBeanFactory(BeanFactory parentBeanFactory) throws IllegalStateException;

 1.4 MessageSource

MessageSource是解析消息的策略接口,支持消息的參數化和國際化。

spring提供兩種開箱即用的可用於生產的實現:

org.springframework.context.support.ResourceBundleMessageSource 基於標準的java.util.ResourceBundle消息解析方式

org.springframework.context.support.ReloadableResourceBundleMessageSource 具備無需重啓VM便可重載消息定義的能力。

 1.5 Application事件機制

1.5.1 EventPublisher事件發佈

ApplicationEventPublisher接口封裝了事件發佈功能,做爲ApplicationContext的父接口使用。

ApplicationEvent:繼承自java.util.EventObject的抽象類,能夠由全部的application事件擴展,但不能做爲直接發佈通用事件的類。經常使用的事件有:

實現發佈的實如今AbstractApplicationConText類中:

/**
     * Publish the given event to all listeners.
     * <p>Note: Listeners get initialized after the MessageSource, to be able
     * to access it within listener implementations. Thus, MessageSource
     * implementations cannot publish events.
     * @param event the event to publish (may be application-specific or a
     * standard framework event)
     */
    @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);
        }
    }

    /**
     * Return the internal ApplicationEventMulticaster used by the context.
     * @return the internal ApplicationEventMulticaster (never {@code null})
     * @throws IllegalStateException if the context has not been initialized yet
     */
    ApplicationEventMulticaster getApplicationEventMulticaster() throws IllegalStateException {
        if (this.applicationEventMulticaster == null) {
            throw new IllegalStateException("ApplicationEventMulticaster not initialized - " +
                    "call 'refresh' before multicasting events via the context: " + this);
        }
        return this.applicationEventMulticaster;
    }

其中

ApplicationEventMulticaster的初始化 來自於AbstractApplicationConText的refresh()方法
public void refresh() throws BeansException, IllegalStateException {
        synchronized (this.startupShutdownMonitor) {
            // Prepare this context for refreshing.
            prepareRefresh();

            // Tell the subclass to refresh the internal bean factory.
            ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

            // Prepare the bean factory for use in this context.
            prepareBeanFactory(beanFactory);

            try {
                // Allows post-processing of the bean factory in context subclasses.
                postProcessBeanFactory(beanFactory);

                // Invoke factory processors registered as beans in the context.
                invokeBeanFactoryPostProcessors(beanFactory);

                // Register bean processors that intercept bean creation.
                registerBeanPostProcessors(beanFactory);

                // Initialize message source for this context.
                initMessageSource();

                // Initialize event multicaster for this context.
                initApplicationEventMulticaster();

                // Initialize other special beans in specific context subclasses.
                onRefresh();

                // Check for listener beans and register them.
                registerListeners();

                // Instantiate all remaining (non-lazy-init) singletons.
                finishBeanFactoryInitialization(beanFactory);

                // Last step: publish corresponding event.
                finishRefresh();
            }

            catch (BeansException ex) {
                logger.warn("Exception encountered during context initialization - cancelling refresh attempt", ex);

                // Destroy already created singletons to avoid dangling resources.
                destroyBeans();

                // Reset 'active' flag.
                cancelRefresh(ex);

                // Propagate exception to caller.
                throw ex;
            }
        }
    }

調用初始化方法:

/**
     * Initialize the ApplicationEventMulticaster.
     * Uses SimpleApplicationEventMulticaster if none defined in the context.
     * @see org.springframework.context.event.SimpleApplicationEventMulticaster
     */
    protected void initApplicationEventMulticaster() {
        ConfigurableListableBeanFactory beanFactory = getBeanFactory();
        if (beanFactory.containsLocalBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME)) {
            this.applicationEventMulticaster =
                    beanFactory.getBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, ApplicationEventMulticaster.class);
            if (logger.isDebugEnabled()) {
                logger.debug("Using ApplicationEventMulticaster [" + this.applicationEventMulticaster + "]");
            }
        }
        else {
            this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);
            beanFactory.registerSingleton(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, this.applicationEventMulticaster);
            if (logger.isDebugEnabled()) {
                logger.debug("Unable to locate ApplicationEventMulticaster with name '" +
                        APPLICATION_EVENT_MULTICASTER_BEAN_NAME +
                        "': using default [" + this.applicationEventMulticaster + "]");
            }
        }
    }

發佈事件的默認實現SimpleApplicationEventMulticaster:

    @Override
    @SuppressWarnings({ "unchecked", "rawtypes" })
    public void multicastEvent(final ApplicationEvent event) {
        for (final ApplicationListener listener : getApplicationListeners(event)) {
            Executor executor = getTaskExecutor();
            if (executor != null) {
                executor.execute(new Runnable() {
                    @Override
                    public void run() {
                        listener.onApplicationEvent(event);
                    }
                });
            }
            else {
                listener.onApplicationEvent(event);
            }
        }
    }

1.5.2 ApplicationListener事件監聽

ApplicationListener application事件監聽器的基礎接口,繼承於java.util.EventListener,基於監聽器涉及模式。

AbstractApplicationContext註冊ApplicationListener監聽器

    /**
     * Add beans that implement ApplicationListener as listeners.
     * Doesn't affect other listeners, which can be added without being beans.
     */
    protected void registerListeners() {
        // Register statically specified listeners first.
        for (ApplicationListener<?> listener : getApplicationListeners()) {
            getApplicationEventMulticaster().addApplicationListener(listener);
        }
        // Do not initialize FactoryBeans here: We need to leave all regular beans
        // uninitialized to let post-processors apply to them!
        String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);
        for (String lisName : listenerBeanNames) {
            getApplicationEventMulticaster().addApplicationListenerBean(lisName);
        }
    }

1.6 ResourcePatternResolver

ResourcePatternResolver是一個解析位置模式(例如ant-樣式的路徑模式)到Resource對象的策略接口。

它擴展了org.springframework.core.io.ResourceLoader接口。內部傳遞的ResourceLoader(例如,在一個運行的context中,org.springframework.context.ApplicationContext的傳遞經過org.springframework.context.ResourceLoaderAware來實現)能夠檢查它的實現是否實現了該擴展接口。

PathMatchingResourcePatternResolver是一個獨立的實現,能夠在Applicationcontext外部使用,也能夠由ResourceArrayPropertyEditor使用來給Resource 數組 bean的屬性。

 ResourceArrayPropertyEditor是一個Resource數組編輯器,自動將位置模式例如file:C:/my*.txt或者classpath*:myfile.txt轉換成Resource數組屬性。一樣,也能夠將一組位置模式轉換成合並的Resource數組。一個路徑也許包含了${...}佔位符,能夠解析成org.springframework.core.env.Environment屬性:如${user.dir}.不能解析的佔位符默認將忽略。

它代理了一個ResourcePatternResolver,默認使用PathMatchingResourcePatternResolver。

1.7 Lifecycle

Lifecycle定義了start/stop方法裏對生命週期進行管理。典型應用是控制異步處理。

能夠由組件(典型的在spring beanFactory定義的spring bean)或者容器(典型的是spring ApplicationContext)。容器將會傳播start/stop信號到它應用的全部組件上。

Lifecycle還能夠經過JMX來直接觸發或者管理各類操做。在後一種應用中,org.springframework.jmx.export.MBeanExporter和org.springframework.jmx.export.assembler.InterfaceBasedMBeanInfoAssembler一塊兒定義活躍的可控組件對Lifecycle的可見性。

注意,Lifecycle接口僅支持最高級別的單實例bean,在別的地方,Lifecycle接口將不會被檢查到而所以被忽略。一樣,注意Lifeclycle的擴展接口SmartLifecycle提供更靈巧的集成容器的啓動和關閉階段。

LifecycleProcessor是一個處理ApplicationContext中bean的生命週期的策略接口。擴展了Lifecycle接口。

默認實現是DefaultLifecycleProcessor

SmartLifecycle是Lifecycle的擴展接口,使用對象是須要在ApplicationContext 刷新或者關閉時一些對象須要有序進行。isAutoStartup()方法返回值表示一個對象是否應該在context刷新時啓動。stop(Runnable)方法的回調在異步關閉進程時很是有用。在整個ApplicationContext關閉時,爲避免沒必要要的延遲,該接口的實現必須在關閉完成時觸發回調的run方法。

這個接口擴展了Phased接口,而且getPhase()方法返回值代表了在組件的生命週期裏應該開始或者中止的階段。進程啓動時擁有最低的階段,結束時擁有最好的階段值(Integer.MIN_VALUE是最低的可能值,Integer.MAX_VALUE是最高的可能值)。進程關閉時則正好相反。具備相同值的組件將會判斷爲處於同一階段。

例如:若是依賴於組件A的組件B已經啓動,那麼組件A應該擁有比組件B更低的階段值。在關閉進程中,組件B應該比組件A更先關閉。Context內的Lifecycle若是沒有實現SmartLifecycle將會認爲其階段值爲0.這種狀況下,具備負的階段值的SmartLifecycle的實現將比這些Lifecycle組件先啓動,或者具備正的階段值的SmartLifecycle的實現比這些Lifecycle晚啓動。

注意:因SmartLifecycle支持auto-startup,在ApplicationContext啓動的任何狀況下,一個SmartLifecycle bean實例將會被初始化。因此,bean定義中的lazy-init屬性將沒法對SmartLifecycle bean產生影響。

Phased 定義了進程所處的階段

/**
 * Interface for objects that may participate in a phased
 * process such as lifecycle management.*/
public interface Phased {

    /**
     * Return the phase value of this object.
     */
    int getPhase();

}

小結:

  本文圍繞ApplicationContext具備的功能,對spring-context的context模塊進行了解釋,只要抓住ApplicationContext的核心就行。

下面列出了BeanFactory提供的功能和ApplicationContext提供的功能(包括其實現)。

特性                                                   BeanFactory   ApplicationContext 
Bean 實例化/裝配                                Yes                 Yes

自動 BeanPostProcessor 註冊                No                  Yes

自動 BeanFactoryPostProcessor 註冊      No                  Yes

便捷的 MessageSource 訪問( i18n)         No                  Yes

ApplicationEvent 發送                         No                  Yes

 加載Resource             No                 Yes         

相關文章
相關標籤/搜索