重點類: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.html。ide
另外還有標準的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