在Web容器(比如Tomcat)中配置Spring时,你可能已经司空见惯于web.xml文件中的以下配置代码:

<context-param><param-name>contextConfigLocation</param-name><param-value>/WEB-INF/applicationContext.xml</param-value></context-param><listener><listener-class>org.springframework.web.context.ContextLoaderListener</listener-class></listener><servlet><servlet-name>mvc-dispatcher</servlet-name><servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class><load-on-startup>1</load-on-startup></servlet><servlet-mapping><servlet-name>mvc-dispatcher</servlet-name><url-pattern>/</url-pattern></servlet-mapping>

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

servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE,this.context);

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

<servlet><servlet-name>customConfiguredDispacherServlet</servlet-name><servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class><init-param><param-name>contextConfigLocation</param-name><param-value>/WEB-INF/dispacherServletContext.xml</param-value></init-param><load-on-startup>1</load-on-startup>
</servlet>

问题是:以上两个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。

参考:http://www.davenkin.me/post/2012-10-18/40039948363

Spring: DispacherServlet和ContextLoaderListener中的WebApplicationContext的关系相关推荐

  1. 重新学习Spring一--Spring在web项目中的启动过程

    1 Spring 在web项目中的启动过程 Spring简介 Spring 最简单的功能就是创建对象和管理这些对象间的依赖关系,实现高内聚.低耦合.(高内聚:相关性很强的代码组成,既单一责任原则:低耦 ...

  2. 在Spring Boot应用程序中测试邮件代码

    在构建Spring Boot应用程序时,您可能会需要添加邮件配置. 实际上,在Spring Boot中配置邮件与在Spring Bootless应用程序中配置邮件没有太大区别. 但是,如何测试邮件配置 ...

  3. 在Spring MVC应用程序中使用Bean Validation 1.1获得更好的错误消息

    在许多新功能中, Bean Validation 1.1引入了使用统一表达式语言(EL)表达式的错误消息插值. 这允许基于条件逻辑来定义错误消息,还可以启用高级格式化选项 . 添加到Spring MV ...

  4. spring mvc在Controller中获取ApplicationContext

    spring mvc在Controller中获取ApplicationContext web.xml中进行正常的beans.xml和spring-mvc.xml的配置: 需要在beans.xml中进行 ...

  5. Spring MVC 在JSP中获取 Service或Dao

    Spring MVC 在JSP中获取service 在Controller.Service层都已经配置好了自动注入,但是在JSP中直接使用 IuserInfoShService uishService ...

  6. Spring Batch在大型企业中的最佳实践

    在大型企业中,由于业务复杂.数据量大.数据格式不同.数据交互格式繁杂,并非所有的操作都能通过交互界面进行处理.而有一些操作需要定期读取大批量的数据,然后进行一系列的后续处理.这样的过程就是" ...

  7. spring mysql mongdb_Spring Boot中使用MongoDB数据库的方法

    MongoDB数据库简介 简介 MongoDB是一个高性能,开源,无模式的,基于分布式文件存储的文档型数据库,由C++语言编写,其名称来源取自"humongous",是一种开源的文 ...

  8. spring配置文件import标签中使用${}占位符获得配置文件的属性值

    2019独角兽企业重金招聘Python工程师标准>>> 一般情况下我们在Spring的配置文件中使用<import>标签是这样的,<import resource= ...

  9. Spring Boot 2.x中如何使用Log4j2记录日志

    前沿技术早知道,弯道超车有希望 积累超车资本,从关注DD开始 上一篇我们介绍了Spring Boot 2.x中默认日志框架Logback的使用.今天继续说说日志,接下来我们要讲是前段时间爆出核弹漏洞的 ...

最新文章

  1. 百度android 测试平台,集成百度活体检测(Android、iOS)
  2. ACCP学习旅程之-----硬件配置
  3. .NET 设计规范--.NET约定、惯用法与模式--6.为扩展性而设计
  4. JAVA——RSA加密【X509EncodedKeySpec、PKCS8EncodedKeySpec、RSAPublicKeySpec、RSAPrivateKeySpec】
  5. 【算法】弗洛伊德算法 最短路径算法
  6. md文件转换为pdf文件(带目录和不带目录简捷操作)
  7. 黑莓手机刷linux,黑莓老机型ROM刷机资源
  8. 天地图key的申请步骤
  9. 华为首款鸿蒙平板发布,华为MatePad Pro发布亮相!华为首款鸿蒙平板全新体验!...
  10. 北洋雷达UST-10LX基于ROS都安装使用测试小问题
  11. div布局改进treeview导航
  12. 互联网的战争--腾讯与360
  13. 浅谈ArcGIS中的容差和分辨率
  14. Redis-NOSQL基础
  15. UG12.0安装 出现 General Fault Exception 是硬件还是软件问题
  16. linux进入字符界面的登录密码,三种进入CentOS界面字符方法
  17. python将多个txt文件导入一个excel的不同sheet中
  18. Unity ParticleSystem制作脚印效果(记录)
  19. Qt Creator配置Intel IPP库并实现信号带通滤波
  20. 列出100以内整数中7的倍数或是含7的数

热门文章

  1. DroidPilot 测试脚本详解 (一)
  2. Yii使用CTreeView树
  3. Go 语言编程 — reflect 反射机制
  4. VMware 虚拟化编程(5) — VixDiskLib 虚拟磁盘库详解之一
  5. 反激式开关电源变压器设计
  6. 几款Java手机看书软件(一)
  7. Mycat分库分表核心技术分析
  8. docker学习系列7 容器化Node项目
  9. lodash(一)数组
  10. DISTINCT 去重---SQL