基于Spring-4.3.7.RELEASE

Spring的配置不仅仅局限在XML文件,同样也可以使用Java代码来配置。在这里我使用XML配置文件的方式来粗略地讲讲WebApplicationContext。

一提到Spring,首先就应该能想到的是IoC和AOP,什么是IoC、AOP不在这里做讲解。Spring提供一个最为基础的IoC容器——BeanFactory,但这个IoC容器所能提供给我们的功能比较少,所以我们通常选用另一个——ApplicationContext(应用上下文)来作为我们的IoC容器,其实ApplicationContext也是继承自BeanFactory,只是在BeanFactory接口基础上做了扩展。那我们这篇文章里要提到的WebApplicationContext不难猜测出它是ApplicationContext的一个实现,在Web应用中我们就利用WebApplicationContext作为我们的IoC容器。

在Web应用中要使用Spring的IoC容器,首要问题就是如何将IoC容器加载到Web容器中。以下是web.xml的部分配置:

<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

这段配置意为给Servlet新增一个监听器,这个监听器需要实现ServletContextListener接口,该接口中有两个方法:

public interface ServletContextListener extends EventListener {
public void contextInitialized(ServletContextEvent sce);  //ServletContext初始化的时候执行此方法
public void contextDestroyed(ServletContextEvent sce);  //ServletContext销毁的时候执行此方法
}

接着来看ContextLoaderListener:

public class ContextLoaderListener extends ContextLoader implements ServletContextListener {
public ContextLoaderListener() {
} public ContextLoaderListener(WebApplicationContext context) {
super(context);
} public void contextInitialized(ServletContextEvent event) {
this.initWebApplicationContext(event.getServletContext());
} public void contextDestroyed(ServletContextEvent event) {
this.closeWebApplicationContext(event.getServletContext());
ContextCleanupListener.cleanupAttributes(event.getServletContext());
}
}

从ContextLoaderListener可以看出WebApplicationContext的初始化实际上是由ContextListener完成的:public void initWebApplicationContext(ServletContext servletContext)

 public void initWebApplicationContext(ServletContext servletContext)
......
if(this.context == null) {
this.context = this.createWebApplicationContext(servletContext); //创建根上下文,在这之前会检查是否已经存在,如果存在则抛出IllegalStateExcpetion异常,跳到第22行
}
......
if(this.context instanceof ConfigurableWebApplicationContext) {
ConfigurableWebApplicationContext err = (ConfigurableWebApplicationContext)this.context;
if(!err.isActive()) {
if(err.getParent() == null) {
ApplicationContext elapsedTime = this.loadParentContext(servletContext);
err.setParent(elapsedTime);
}
this.configureAndRefreshWebApplicationContext(err, servletContext); //ApplicationContext上下文创建好后对其进行赋值和初始化,跳到第31行
}
}
//将WebApplicationContext根上下文绑定到Web应用程序的ServletContext上.
servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, this.context);
.....
return this.context;
}
protected WebApplicationContext createWebApplicationContext(ServletContext sc) {
Class contextClass = this.determineContextClass(sc); //判断使用什么样的类在Web容器中作为IoC容器,跳到第26行
......
}
protected Class<?> determineContextClass(ServletContext servletContext) {
String contexClassName = servlet.getInitParameter(CONTEXT_CLASS_PARAM); //读取web.xml中的配置<context-param>contextClass</context-param>
//如果配置了需要使用的CONTEXT_CLASS,那就是用这个class,如果没有额外的配置,就是用默认的ContextClass也就是XmlWebApplicationContext.
}
//设置IoC容器的参数,并通过refresh启动容器的初始化
protected void configureAndRefreshWebApplicationContext(ConfigurableWebApplicationContext wac, ServletContext sc){
String configLocationParam;
if(ObjectUtils.identityToString(wac).equals(wac.getId())) {
configLocationParam = sc.getInitParameter("contextId");
if(configLocationParam != null) {
wac.setId(configLocationParam);
} else {
wac.setId(ConfigurableWebApplicationContext.APPLICATION_CONTEXT_ID_PREFIX + ObjectUtils.getDisplayString(sc.getContextPath()));
}
}
wac.setServletContext(sc);
configLocationParam = sc.getInitParameter(CONFIG_LOCATION_PARAM); //contextConfigLocation,Spring根应用上下文重要的配置文件,很多bean的定义等等
......
wac.refresh(); //启动容器的初始化
}

以上代码第27行所述web.xml中配置指定的IoC容器:

<context-param>
<param-name>contextClass</param-name>
<param-value>org.springframework.web.context.support.AnnotationConfigWebApplicationContext</param-value>
</context-param>

以上代码第42行所述web.xml中配置指定的IoC容器:

<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath*:applicationContext.xml</param-value>
</context-param>

上面这段配置就是自定义要使用的IoC容器而不使用默认的XmlApplicationContext容器.

第7行代码开始,当ApplicationContext上下文建立起来过后,也就是Web应用中的IoC容器建立起来过后,接下来就是applicationContext设置一些参数例如它的双亲.至此在Web应用环境中的IoC容器就已经完成了初始化,由于要考虑Web容器的环境特别,比如各种参数的设置,所以在上面的代码能看出首先创建了IoC容器,其次再为容器赋一些参数值,最后还有IoC容器和Web容器SevletContext的结合作为全局应用上下文.在接下来会介绍在启动Spring MVC时DispatcherServert在进行自己持有的上下文的初始化时,将ApplicationContext根应用上下文设置为DispatcherServlet的双亲上下文.

Spring——Web应用中的IoC容器创建(WebApplicationContext根应用上下文的创建过程)的更多相关文章

  1. Spring学习(四)在Web项目中实例化IOC容器

    1.前言 前面我们讲到Spring在普通JAVA项目中的一些使用.本文将介绍在普通的Web项目中如何实例化Spring IOC容器.按照一般的思路.如果在Web中实例化Ioc容器.这不得获取Conte ...

  2. Spring在非web应用中关闭IoC容器 (registerShutdownHook)

    在基于web的ApplicationContext实现中,已有相应的实现来处理关闭web应用时恰当地关闭Spring IoC容器.但,如果你正在一个非web应用的环境下使用Spring的IoC容器,如 ...

  3. Spring源码分析专题 —— IOC容器启动过程(上篇)

    声明 1.建议先阅读<Spring源码分析专题 -- 阅读指引> 2.强烈建议阅读过程中要参照调用过程图,每篇都有其对应的调用过程图 3.写文不易,转载请标明出处 前言 关于 IOC 容器 ...

  4. 目标HttpController在ASP.NET Web API中是如何被激活的:目标HttpController的创建

    目标HttpController在ASP.NET Web API中是如何被激活的:目标HttpController的创建 通过上面的介绍我们知道利用HttpControllerSelector可以根据 ...

  5. 【spring源码分析】IOC容器初始化(总结)

    前言:在经过前面十二篇文章的分析,对bean的加载流程大致梳理清楚了.因为内容过多,因此需要进行一个小总结. 经过前面十二篇文章的漫长分析,终于将xml配置文件中的bean,转换成我们实际所需要的真正 ...

  6. 【spring源码分析】IOC容器初始化(二)

    前言:在[spring源码分析]IOC容器初始化(一)文末中已经提出loadBeanDefinitions(DefaultListableBeanFactory)的重要性,本文将以此为切入点继续分析. ...

  7. 【spring源码分析】IOC容器初始化(三)

    前言:在[spring源码分析]IOC容器初始化(二)中已经得到了XML配置文件的Document实例,下面分析bean的注册过程. XmlBeanDefinitionReader#registerB ...

  8. 【spring源码分析】IOC容器初始化(四)

    前言:在[spring源码分析]IOC容器初始化(三)中已经分析了BeanDefinition注册之前的一些准备工作,下面将进入BeanDefinition注册的核心流程. //DefaultBean ...

  9. 【spring源码分析】IOC容器初始化(七)

    前言:在[spring源码分析]IOC容器初始化(六)中分析了从单例缓存中加载bean对象,由于篇幅原因其核心函数 FactoryBeanRegistrySupport#getObjectFromFa ...

随机推荐

  1. 【C语言】模拟实现atoi函数

    atoi(表示 ascii to integer)是把字符串转换成整型数的一个函数. atoi()函数会扫描参数 nptr字符串,跳过前面的空白字符(例如空格,tab缩进等,可以通过isspace( ...

  2. 请不要把‘通知的观察者注册’放在-viewWillAppear:中

    接手项目二次开发的吐槽: 接手别人的代码的悲哀之一就是,我反复的把流程走了一遍又一遍,却始终无法发现原来是这个问题. 之前这个人把通知的观察者注册放在了-viewWillAppear:中,导致,我发送 ...

  3. --save 和 --save-dev的区别

    --save是对生产环境所需依赖的声明(开发应用中使用的框架,库,比如jquery,bootstrap等) --save-dev是对开发环境所需依赖的声明(构建工具,测试工具,比如babel,gulp ...

  4. 服务器上的Git

    前面的话 如果想与他人使用,除了使用Git来完成日常工作之外,还需要一个远程的Git仓库.尽管从技术上可以从个人的仓库里推送和拉取修改内容,但并不鼓励这样做,因为一不留心就很容易弄混其他人的进度.因此 ...

  5. transform-origin 的定位

    transform-origin接受两个参数,它们可以是百分比,em,px等具体的值,也可以是left,center,right,或者 top,center,bottom等描述性参数,第一个参数表示X ...

  6. Filter execution threw an exception 错误

    Filter execution threw an exception 错误,我在web.xml中配置了一个filter用spring来解决懒加载的问题,为什么就会包这个错 java.lang.NoS ...

  7. [编织消息框架][网络IO模型]BIO

    既然跟网络内容有关就不得不学习网络IO模型,时代在进步,技术也在进步,采取使用那种网络IO模型就已经确定应用程序规模 阻塞IO(blocking IO) 在linux中,默认情况下所有的socket都 ...

  8. 一款好用的jquery评分插件

    一.使用说明 1.jQuery评分插件的功能: 图标显示用户评分,更美观 可实时点击,切换评分 返回用户评分,记录用户评分 实现类似下图效果 2.优点: 美观,方便 3.缺点: 只能用于jquery开 ...

  9. h5 实现调用系统拍照或者选择照片并预览

    这次又来分享个好东西! 调用手机相机拍照或者是调用手机相册选择照片,这个功能在 手机端页面 或者 webApp 应该是常用到的,就拿个人或会员资料录入那块来说就已经是经常会碰到的, 每当看到这块功能的 ...

  10. Wireshark的专家模式

    -------------------------------本文作为留档文章已备查看----------------------------------- Wireshark的每个协议的解析器(原始 ...