Spring——Web应用中的IoC容器创建(WebApplicationContext根应用上下文的创建过程)
基于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根应用上下文的创建过程)的更多相关文章
- Spring学习(四)在Web项目中实例化IOC容器
1.前言 前面我们讲到Spring在普通JAVA项目中的一些使用.本文将介绍在普通的Web项目中如何实例化Spring IOC容器.按照一般的思路.如果在Web中实例化Ioc容器.这不得获取Conte ...
- Spring在非web应用中关闭IoC容器 (registerShutdownHook)
在基于web的ApplicationContext实现中,已有相应的实现来处理关闭web应用时恰当地关闭Spring IoC容器.但,如果你正在一个非web应用的环境下使用Spring的IoC容器,如 ...
- Spring源码分析专题 —— IOC容器启动过程(上篇)
声明 1.建议先阅读<Spring源码分析专题 -- 阅读指引> 2.强烈建议阅读过程中要参照调用过程图,每篇都有其对应的调用过程图 3.写文不易,转载请标明出处 前言 关于 IOC 容器 ...
- 目标HttpController在ASP.NET Web API中是如何被激活的:目标HttpController的创建
目标HttpController在ASP.NET Web API中是如何被激活的:目标HttpController的创建 通过上面的介绍我们知道利用HttpControllerSelector可以根据 ...
- 【spring源码分析】IOC容器初始化(总结)
前言:在经过前面十二篇文章的分析,对bean的加载流程大致梳理清楚了.因为内容过多,因此需要进行一个小总结. 经过前面十二篇文章的漫长分析,终于将xml配置文件中的bean,转换成我们实际所需要的真正 ...
- 【spring源码分析】IOC容器初始化(二)
前言:在[spring源码分析]IOC容器初始化(一)文末中已经提出loadBeanDefinitions(DefaultListableBeanFactory)的重要性,本文将以此为切入点继续分析. ...
- 【spring源码分析】IOC容器初始化(三)
前言:在[spring源码分析]IOC容器初始化(二)中已经得到了XML配置文件的Document实例,下面分析bean的注册过程. XmlBeanDefinitionReader#registerB ...
- 【spring源码分析】IOC容器初始化(四)
前言:在[spring源码分析]IOC容器初始化(三)中已经分析了BeanDefinition注册之前的一些准备工作,下面将进入BeanDefinition注册的核心流程. //DefaultBean ...
- 【spring源码分析】IOC容器初始化(七)
前言:在[spring源码分析]IOC容器初始化(六)中分析了从单例缓存中加载bean对象,由于篇幅原因其核心函数 FactoryBeanRegistrySupport#getObjectFromFa ...
随机推荐
- 动态代理的两种实现方式(JDK/Cglib)
=========================================== 原文链接: 动态代理的两种实现方式(JDK/Cglib) 转载请注明出处! ================== ...
- 老李推荐:第6章5节《MonkeyRunner源码剖析》Monkey原理分析-事件源-事件源概览-事件
老李推荐:第6章5节<MonkeyRunner源码剖析>Monkey原理分析-事件源-事件源概览-事件 从网络过来的命令字串需要解析翻译出来,有些命令会在翻译好后直接执行然后返回,但有 ...
- Ubuntu16.04部署python2和python3共存的Jupyter Notebook
一.安装python和python-pip sudo apt-get install python python3 python-pip python3-pip sudo pip install -- ...
- 【学而思】利用shouldComponentUpdate钩子函数优化react性能以及引入immutable库的必要性
凡是参阅过react官方英文文档的童鞋大体上都能知道对于一个组件来说,其state的改变(调用this.setState()方法)以及从父组件接受的props发生变化时,会导致组件重渲染,正所谓&qu ...
- 关于AysncController的一次测试(url重写后静态页文件内容的读取是否需要使用异步?)
因为做网站的静态页缓存,所以做了这个测试 MVC项目 准备了4个Action,分两组,一组是读取本地磁盘的一个html页面文件,一组是延时2秒 public class TestController ...
- R中基本统计图
一.条形图 1.安装包install.packages("vcd"); library(vcd);count<-table(Arthritis$Improved);#tabl ...
- HTML5 模拟现实物理效果
Ball Pool 是一个基于 HTML5 技术的实验,模拟现实物理效果,让你在 Web 中感受自然物体的运动.玩法介绍:可以随意拖动圆球.点击页面背景.晃动浏览器.双击页面背景或者按住鼠标左键,有不 ...
- [ext4]04 磁盘布局 - Meta Block Groups
Meta Block Groups,可以翻译为元块组集. 如果不采用Meta Block Groups特性,在每个冗余备份的超级块的后面是一个完整的(包含所有块组描述符的)块组描述符表的备份.如前所述 ...
- CSS3 02. 边框、边框圆角、边框阴影、边框图片、渐变、线性渐变、径向渐变、背景、过渡transition、2D转换
边框圆角 border-radius 每个角可以设置两个值,x值.y值 border-top-left-radius:水平半径 垂直半径 border-radius:水平半径/垂直半径 border- ...
- crontab的两种配置方式
废话不多说,直接上菜了 第一种:在/etc/crontab下设置,指定用户名的 1.vim命令进入/etc/crontab 2.在最后一行加上 59 23 * * * root /root/cat ...