重点类:

1、ApplicationContext是核心接口,它为一个应用提供了环境配置。当应用在运行时ApplicationContext是只读的,但你可以在该接口的实现中来支持reload功能。

定义

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

特点:

提供了一个bean工厂方法来访问应用组件,通过继承org.springframework.beans.factory.ListableBeanFactory来获得的;

通过通用的方式来加载文件资源的能力,通过继承org.springframework.core.io.ResourceLoader来获得的;

发布事件到注册的监听器的能力,通过继承ApplicationEventPublisher来获得的;

解析消息,支持国际化的能力,通过继承MessageSource来获得的;

context的继承机制。定义在子context将优先级别更高。这意味着,例如:一个父context可以被整个web应用共享,而每个servlet可以有自己的子context,并且这些servlet彼此独立。例如http://www.cnblogs.com/davidwang456/p/4122842.html

另外还有标准的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         

spring源码分析之context的更多相关文章

  1. spring源码分析之<context:property-placeholder/>和<property-override/>

    在一个spring xml配置文件中,NamespaceHandler是DefaultBeanDefinitionDocumentReader用来处理自定义命名空间的基础接口.其层次结构如下: < ...

  2. spring源码分析之<context:component-scan/>vs<annotation-config/>

    1.<context:annotation-config/> xsd中说明: <xsd:element name="annotation-config"> ...

  3. Spring源码分析——BeanFactory体系之抽象类、类分析(二)

    上一篇分析了BeanFactory体系的2个类,SimpleAliasRegistry和DefaultSingletonBeanRegistry——Spring源码分析——BeanFactory体系之 ...

  4. Spring源码分析——资源访问利器Resource之实现类分析

    今天来分析Spring的资源接口Resource的各个实现类.关于它的接口和抽象类,参见上一篇博文——Spring源码分析——资源访问利器Resource之接口和抽象类分析 一.文件系统资源 File ...

  5. spring源码分析(二)Aop

    创建日期:2016.08.19 修改日期:2016.08.20-2016.08.21 交流QQ:992591601 参考资料:<spring源码深度解析>.<spring技术内幕&g ...

  6. spring源码分析

    编译问题 spring-4.0.5.release编译是用jdk8编译的,为啥可以运行在jdk7的环境? 源码分析 spring源码分析,由一个点各个击破,比如依赖注入,autowired. spri ...

  7. 【Spring源码分析】Bean加载流程概览

    代码入口 之前写文章都会啰啰嗦嗦一大堆再开始,进入[Spring源码分析]这个板块就直接切入正题了. 很多朋友可能想看Spring源码,但是不知道应当如何入手去看,这个可以理解:Java开发者通常从事 ...

  8. 【Spring源码分析】非懒加载的单例Bean初始化前后的一些操作

    前言 之前两篇文章[Spring源码分析]非懒加载的单例Bean初始化过程(上篇)和[Spring源码分析]非懒加载的单例Bean初始化过程(下篇)比较详细地分析了非懒加载的单例Bean的初始化过程, ...

  9. 【Spring源码分析】配置文件读取流程

    前言 Spring配置文件读取流程本来是和http://www.cnblogs.com/xrq730/p/6285358.html一文放在一起的,这两天在看Spring自定义标签的时候,感觉对Spri ...

随机推荐

  1. 使用 Roslyn 编译器服务

    .NET Core和 .NET 4.6中 的C# 6/7 中的编译器Roslyn 一个重要的特性就是"Compiler as a Service",简单的讲,就是就是将编译器开放为 ...

  2. 记一次SQLServer的分页优化兼谈谈使用Row_Number()分页存在的问题

    最近有项目反应,在服务器CPU使用较高的时候,我们的事件查询页面非常的慢,查询几条记录竟然要4分钟甚至更长,而且在翻第二页的时候也是要这么多的时间,这肯定是不能接受的,也是让现场用SQLServerP ...

  3. 从Membership 到 .NET4.5 之 ASP.NET Identity

    我们前面已经讨论过了如何在一个网站中集成最基本的Membership功能,然后深入学习了Membership的架构设计.正所谓从实践从来,到实践从去,在我们把Membership的结构吃透之后,我们要 ...

  4. 无法向会话状态服务器发出会话状态请求。请确保 ASP.NET State Service (ASP.NET 状态服务)已启动,并且客户端端口与服务器端口相同。如果服务器位于远程计算机上,请检查。。。

    异常处理汇总-服 务 器 http://www.cnblogs.com/dunitian/p/4522983.html 无法向会话状态服务器发出会话状态请求.请确保 ASP.NET State Ser ...

  5. 03.LoT.UI 前后台通用框架分解系列之——多样的表格

    LOT.UI分解系列汇总:http://www.cnblogs.com/dunitian/p/4822808.html#lotui LoT.UI开源地址如下:https://github.com/du ...

  6. JavaScript Array对象

    介绍Js的Array 数组对象. 目录 1. 介绍:介绍 Array 数组对象的说明.定义方式以及属性. 2. 实例方法:介绍 Array 对象的实例方法:concat.every.filter.fo ...

  7. [OpenGL超级宝典]专栏前言

    我小时候的梦想呢,是做宇航员或者科学家或者是做一款属于自己的游戏,后来前面两个梦想都没有实现,于是我就来实现我的第三个梦想了,,,我呢,也算是零基础,因为我的专业是物联网工程,这个专业覆盖面之广,简直 ...

  8. MySQL 系列(一) 生产标准线上环境安装配置案例及棘手问题解决

    一.简介 MySQL是最流行的开放源码SQL数据库管理系统,它是由MySQL AB公司开发.发布并支持的.有以下特点: MySQL是一种数据库管理系统. MySQL是一种关联数据库管理系统. MySQ ...

  9. java观察者模式

      像activeMQ等消息队列中,我们经常会使用发布订阅模式,但是你有没有想过,客户端时如何及时得到订阅的主题的信息?其实就里就用到了观察者模式.在软件系统中,当一个对象的行为依赖于另一个对象的状态 ...

  10. Angular2 Hello World 之 2.0

    最近angular2正式版发布了,现在就趁热接着记录一下2.0版的Hello World.据说由RC6升级到2.0代码改动不是很大,在写的时候也感觉改动不是很大,这次记录还是以asp.net core ...