转自:http://blog.csdn.net/c289054531/article/details/9196149?utm_source=tuicool&utm_medium=referral

解释一:

要想很好理解这三个上下文的关系,需要先熟悉spring是怎样在web容器中启动起来的。spring的启动过程其实就是其IoC容器的启动过程,对于web程序,IoC容器启动过程即是建立上下文的过程。

spring的启动过程:

  1. 首先,对于一个web应用,其部署在web容器中,web容器提供其一个全局的上下文环境,这个上下文就是ServletContext,其为后面的spring IoC容器提供宿主环境;

  2. 其次,在web.xml中会提供有contextLoaderListener。在web容器启动时,会触发容器初始化事件,此时contextLoaderListener会监听到这个事件,其contextInitialized方法会被调用,在这个方法中,spring会初始化一个启动上下文,这个上下文被称为根上下文,即WebApplicationContext,这是一个接口类,确切的说,其实际的实现类是XmlWebApplicationContext。这个就是spring的IoC容器,其对应的Bean定义的配置由web.xml中的context-param标签指定。在这个IoC容器初始化完毕后,spring以WebApplicationContext.ROOTWEBAPPLICATIONCONTEXTATTRIBUTE为属性Key,将其存储到ServletContext中,便于获取;

  3. 再次,contextLoaderListener监听器初始化完毕后,开始初始化web.xml中配置的Servlet,这个servlet可以配置多个,以最常见的DispatcherServlet为例,这个servlet实际上是一个标准的前端控制器,用以转发、匹配、处理每个servlet请求。DispatcherServlet上下文在初始化的时候会建立自己的IoC上下文,用以持有spring mvc相关的bean。在建立DispatcherServlet自己的IoC上下文时,会利用WebApplicationContext.ROOTWEBAPPLICATIONCONTEXTATTRIBUTE先从ServletContext中获取之前的根上下文(即WebApplicationContext)作为自己上下文的parent上下文。有了这个parent上下文之后,再初始化自己持有的上下文。这个DispatcherServlet初始化自己上下文的工作在其initStrategies方法中可以看到,大概的工作就是初始化处理器映射、视图解析等。这个servlet自己持有的上下文默认实现类也是mlWebApplicationContext。初始化完毕后,spring以与servlet的名字相关(此处不是简单的以servlet名为Key,而是通过一些转换,具体可自行查看源码)的属性为属性Key,也将其存到ServletContext中,以便后续使用。这样每个servlet就持有自己的上下文,即拥有自己独立的bean空间,同时各个servlet共享相同的bean,即根上下文(第2步中初始化的上下文)定义的那些bean。

解释二:

    在Web容器(比如Tomcat)中配置Spring时,你可能已经司空见惯于web.xml文件中的以下配置代码:
  1. <span style="font-family:SimSun;font-size:14px;"><context-param>
  2. <param-name>contextConfigLocation</param-name>
  3. <param-value>/WEB-INF/applicationContext.xml</param-value>
  4. </context-param>
  5. <listener>
  6. <listener-class>
  7. org.springframework.web.context.ContextLoaderListener
  8. </listener-class>
  9. </listener>
  10. <servlet>
  11. <servlet-name>mvc-dispatcher</servlet-name>
  12. <servlet-class>
  13. org.springframework.web.servlet.DispatcherServlet
  14. </servlet-class>
  15. <load-on-startup>1</load-on-startup>
  16. </servlet>
  17. <servlet-mapping>
  18. <servlet-name>mvc-dispatcher</servlet-name>
  19. <url-pattern>/</url-pattern>
  20. </servlet-mapping></span>

以上配置首先会在ContextLoaderListener中通过<context-param>中的applicationContext.xml创建一个ApplicationContext,再将这个ApplicationContext塞到ServletContext里面,通过ServletContext的setAttribute方法达到此目的,在ContextLoaderListener的源代码中,我们可以看到这样的代码:

  1. <span style="font-family:SimSun;font-size:14px;">servletContext.setAttribute(
  2. WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE,
  3. this.context);</span>

以上由ContextLoaderListener创建的ApplicationContext是共享于整个Web应用程序的,而你可能早已经知道,DispatcherServlet会维持一个自己的ApplicationContext,默认会读取/WEB-INFO/<dispatcherServletName>-servlet.xml文件,而我么也可以重新配置:

  1. <span style="font-family:SimSun;font-size:14px;"><servlet>
  2. <servlet-name>
  3. customConfiguredDispacherServlet
  4. </servlet-name>
  5. <servlet-class>
  6. org.springframework.web.servlet.DispatcherServlet
  7. </servlet-class>
  8. <init-param>
  9. <param-name>
  10. contextConfigLocation
  11. </param-name>
  12. <param-value>
  13. /WEB-INF/dispacherServletContext.xml
  14. </param-value>
  15. </init-param>
  16. <load-on-startup>1</load-on-startup>
  17. </servlet></span>

问题是:以上两个ApplicationContext的关系是什么,它们的作用作用范围分别是什么,它们的用途分别是什么?

ContextLoaderListener中创建ApplicationContext主要用于整个Web应用程序需要共享的一些组件,比如DAO,数据库的ConnectionFactory等。而由DispatcherServlet创建的ApplicationContext主要用于和该Servlet相关的一些组件,比如Controller、ViewResovler等。

对于作用范围而言,在DispatcherServlet中可以引用由ContextLoaderListener所创建的ApplicationContext,而反过来不行。

在Spring的具体实现上,这两个ApplicationContext都是通过ServletContext的setAttribute方法放到ServletContext中的。但是,ContextLoaderListener会先于DispatcherServlet创建ApplicationContext,DispatcherServlet在创建ApplicationContext时会先找到由ContextLoaderListener所创建的ApplicationContext,再将后者的ApplicationContext作为参数传给DispatcherServlet的ApplicationContext的setParent()方法,在Spring源代码中,你可以在FrameServlet.Java中找到如下代码:

    wac.setParent(parent);

其中,wac即为由DisptcherServlet创建的ApplicationContext,而parent则为有ContextLoaderListener创建的ApplicationContext。此后,框架又会调用ServletContext的setAttribute()方法将wac加入到ServletContext中。

    当Spring在执行ApplicationContext的getBean时,如果在自己context中找不到对应的bean,则会在父ApplicationContext中去找。这也解释了为什么我们可以在DispatcherServlet中获取到由ContextLoaderListener对应的ApplicationContext中的bean。

【转】 spring context解惑的更多相关文章

  1. [转载]vs2012中使用Spring.NET报错:Spring.Context.Support.ContextRegistry 的类型初始值设定项引发异常

    学习使用Spring.NET中的时候,写了一个Demo,在运行时报了一个错误:Spring.Context.Support.ContextRegistry 的类型初始值设定项引发异常. 重新整理思绪, ...

  2. Spring context:component-scan中使用context:include-filter和context:exclude-filter

    Spring context:component-scan中使用context:include-filter和context:exclude-filter XML: <?xml version= ...

  3. Spring context:component-scan代替context:annotation-config

    Spring context:component-scan代替context:annotation-config XML: <?xml version="1.0" encod ...

  4. Spring <context:component-scan>标签属性 use-default-filters 以及子标签 include-filter使用说明

    Spring <context:component-scan>标签作用有很多,最基本就是 开启包扫描,可以使用@Component.@Service.@Component等注解: 今天要作 ...

  5. 使用web.xml方式加载Spring时,获取Spring context的两种方式

    使用web.xml方式加载Spring时,获取Spring context的两种方式: 1.servlet方式加载时: [web.xml] <servlet> <servlet-na ...

  6. 【报错】spring整合activeMQ,pom.xml文件缺架包,启动报错:Caused by: java.lang.ClassNotFoundException: org.apache.xbean.spring.context.v2.XBeanNamespaceHandler

    spring版本:4.3.13 ActiveMq版本:5.15 ======================================================== spring整合act ...

  7. Spring Context 你真的懂了吗

    今天介绍一下大家常见的一个单词 context 应该怎么去理解,正确的理解它有助于我们学习 spring 以及计算机系统中的其他知识. 1. context 是什么 我们经常在编程中见到 contex ...

  8. Spring context的refresh函数执行过程分析

    今天看了一下Spring Boot的run函数运行过程,发现它调用了Context中的refresh函数.所以先分析一下Spring context的refresh过程,然后再分析Spring boo ...

  9. spring context上下文(应用上下文webApplicationContext)(转载)

    (此文转载:http://www.cnblogs.com/brolanda/p/4265597.html) 一.先说ServletContext javaee标准规定了,servlet容器需要在应用项 ...

随机推荐

  1. javascript中的装箱和拆箱操作

    1,装箱: 把基本数据类型转换为对应的引用类型的操作称为装箱,把引用类型转换为基本的数据类型称为拆箱. 在<javascript高级程序设计>中有这样一句话: 每当读取一个基本类型的时候, ...

  2. 安卓Animation类与xml制作动画

    有时要对控件添加一点动画效果,在安卓中,动画效果也是一个类,也就是Animation类.把动画效果这个类弄好后,在与控件类关联到一起,就可以实现控件有一些动作特效这样的效果了.动画效果的定义,要在xm ...

  3. How To Install Git on CentOS 7

    Introduction Version control has become an indispensable tool in modern software development. Versio ...

  4. leetcode876

    class Solution { public: ListNode* middleNode(ListNode* head) { if (head == NULL) { return nullptr; ...

  5. ubuntu14.10下Qt5.4无法输入中文

    最近学习Qt,于是在ubuntu下安装了开发环境.我是从官网上下载安装的Qt5.4版本.安装后发现在开发过程中无法输入中文.于是在网上搜了搜.解决办法如下: 1.安装fcitx-frontend-qt ...

  6. js格式化时间和时间操作

    js格式化时间 function formatDateTime(inputTime) { var date = new Date(inputTime); var y = date.getFullYea ...

  7. Unity抗锯齿的设置

    [Unity抗锯齿的设置] "Edit"->"Project Settings"->"Quality",可以质量设置Inspec ...

  8. 使用RandomAccessFile读写数据

    ------------siwuxie095 工程名:TestRandomAccessFile 包名:com.siwuxie095.file 类名:MultiWriteFile.java(主类).Wr ...

  9. WebFlux04 SpringBootWebFlux集成MongoDB之Windows版本、WebFlux实现CRUD、WebFlux实现JPA、参数校验

    1 下载并安装MongoDB 1.1 MongoDB官网 1.2 下载 solutions -> download center 1.3 安装 双击进入安装即可 1.3.1 安装时常见bug01 ...

  10. 模板模式和Comparable类

    模板模式中,父类规定好了一些算法的流程,并且空出一些步骤(方法)留给子类填充 Java的数组类中静态方法sort()就是一个模板,它空出了一个compareTo的方法,留给子类填充,用来规定什么是大于 ...