重点类: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