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) 

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

 以上代码第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的双亲上下文.

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏清晨我上码

第十四节 springcould zuul边缘路由的使用

其他具体配置及功能可参考源码zuul服务源码 需要说明需要启动本zuul项目,需要依赖eureka server、security-server、以及其他业务...

2833
来自专栏芋道源码1024

注册中心 Eureka 源码解析 —— Eureka-Server 启动(二)之 EurekaBootStrap

本文主要基于 Eureka 1.8.X 版本 1. 概述 2. EurekaBootStrap 2.1 初始化 Eureka-Server 配置环境 2.2 初...

7984
来自专栏程序你好

Spring Security与OAuth2

Spring Security为基于j2ee的企业软件应用程序提供了全面的安全服务。它强大、灵活、可插。它不像代理服务器、防火墙、OS级别安全性、入侵检测系统或...

1743
来自专栏菩提树下的杨过

mac:在当前文件夹打开terminal终端

System Preferences -> Keyboard -> Shortcuts -> Services -> New Terminal at Folde...

2348
来自专栏Laoqi's Linux运维专列

LAMP安装mysql 时遇到的问题汇总

1: 缺少 libaio 包, libaio是Linux下的一个异步非阻塞方式读写文件的接口。 1 2 3 [[email protect...

3916
来自专栏技术总结

献给移动端的服务器搭建

application.properties这个是项目的一些配置,举例一下默认是8080端口,我们如果想改下端口的话,就可以在配置增加

2672
来自专栏程序猿DD

Spring Boot使用@Async实现异步调用:ThreadPoolTaskScheduler线程池的优雅关闭

上周发了一篇关于Spring Boot中使用 @Async来实现异步任务和线程池控制的文章:《Spring Boot使用@Async实现异步调用:自定义线程池》...

6427
来自专栏菩提树下的杨过

Spring Security笔记:使用数据库进行用户认证(form login using database)

在前一节,学习了如何自定义登录页,但是用户名、密码仍然是配置在xml中的,这样显然太非主流,本节将学习如何把用户名/密码/角色存储在db中,通过db来实现用户认...

1961
来自专栏一个会写诗的程序员的博客

Circular view path [addKnowledge]: would dispatch back to the current handler URL

1271
来自专栏bboysoul

linux编译安装apache

wget http://mirrors.ustc.edu.cn/apache/httpd/httpd-2.4.25.tar.gz tar -zxvf http...

2773

扫码关注云+社区

领取腾讯云代金券