spring和springMVC父子容器的原理

转载 2018年04月15日 19:57:21

要想很好理解这三个上下文的关系,需要先熟悉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。

说完了spring上下文的初始化过程,这三个上下文的关系应该就了解了。如还是不太清楚,我就爱莫能助了,只能自行看代码去了。

===============================================================================================================

最近在做项目时牵扯到有关父子上下文的概念。

何为父子上下文呢?

父上下文:

使用listener监听器来加载配置文件,如下:

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

Spring 会创建一个WebApplicationContext上下文,称为父上下文(父容器),保存在 ServletContext中,key是WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE的值。

可以使用Spring提供的工具类取出上下文对象:WebApplicationContextUtils.getWebApplicationContext(ServletContext);

子上下文:

使用Spring MVC 来处理拦截相关的请求时,会配置DispatchServlet:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<servlet>
    <servlet-name>dispatcherServlet</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet
    </servlet-class>
    <init-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>/WEB-INF/applicationContext-mvc.xml</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
</servlet>
 
<servlet-mapping>
    <servlet-name>dispatcherServlet</servlet-name>
    <url-pattern>/</url-pattern>
</servlet-mapping>

每个DispatchServlet会有一个自己的上下文,称为子上下文,它也保存在 ServletContext中,key 是"org.springframework.web.servlet.FrameworkServlet.CONTEXT"+Servlet名称。当一 个Request对象产生时,会把这个子上下文对象(WebApplicationContext)保存在Request对象中,key是 DispatcherServlet.class.getName() + ".CONTEXT"。

可以使用工具类取出上下文对象:RequestContextUtils.getWebApplicationContext(request);


父上下文(父容器)和子上下文(子容器)的访问权限:

子上下文可以访问父上下文中的bean,但是父上下文不可以访问子上下文中的bean。


父上下文使用与否

方案一,传统型:

父上下文容器中保存数据源、服务层、DAO层、事务的Bean。

子上下文容器中保存Mvc相关的Action的Bean.

事务控制在服务层。

由于父上下文容器不能访问子上下文容器中内容,事务的Bean在父上下文容器中,无法访问子上下文容器中内容,就无法对子上下文容器中Action进行AOP(事务)。

当然,做为“传统型”方案,也没有必要这要做。

 

方案二,激进型:

Java世界的“面向接口编程”的思想是正确的,但在增删改查为主业务的系统里,Dao层接口,Dao层实现类,Service层接口,Service层实现类,Action父类,Action。再加上众多的O(vo\po\bo)和jsp页面。写一个小功能 7、8个类就写出来了。 开发者说我就是想接点私活儿,和PHP,ASP抢抢饭碗,但我又是Java程序员。最好的结果是大项目能做好,小项目能做快。所以“激进型”方案就出现了-----没有接口、没有Service层、还可以没有众多的O(vo\po\bo)。那没有Service层事务控制在哪一层?只好上升的Action层。

本文不想说这是不是正确的思想,我想说的是Spring不会限制你这样做。

由于有了父子上下文,你将无法实现这一目标。解决方案是只使用子上下文容器,不要父上下文容器 。所以数据源、服务层、DAO层、事务的Bean、Action的Bean都放在子上下文容器中。就可以实现了,事务(注解事务)就正常工作了。这样才够激进。

总结:不使用listener监听器来加载spring的配置文件,只使用DispatcherServlet来加载spring的配置,不要父子上下文,只使用一个DispatcherServlet,事情就简单了,什么麻烦事儿也没有了。

 

 

 

Java--大项目能做好--按传统方式做,规规矩矩的做,好扩展,好维护。

Java--小项目能做快--按激进方式做,一周时间就可以出一个版本,先上线接受市场(用户)的反馈,再改进,再反馈,时间就是生命(成本)。

spring的启动过程——spring和springMVC父子容器的原理

要想很好理解这三个上下文的关系,需要先熟悉spring是怎样在web容器中启动起来的。spring的启动过程其实就是其IoC容器的启动过程,对于web程序,IoC容器启动过程即是建立上下文的过程。 ...
  • caomiao2006
  • caomiao2006
  • 2016-05-01 15:04:33
  • 17335

spring 和 springmvc 的父子容器关系浅析

spring 和springmvc 的父子容器 @controller中访问属性文件配置的属性 spring和spring mvc 中加载属性文件的顺序...
  • liudongdong0909
  • liudongdong0909
  • 2016-04-07 18:55:33
  • 3785

spring和springmvc父子容器关系

今天碰到一个问题,在springmvc.xml中配置后加载不了properties配置文件中的属性,而在applicationContext-*.xml中配置却可以正常加载到属性,这个问题其实就涉及到...
  • cfp008
  • cfp008
  • 2016-12-21 00:12:11
  • 359

spring和springmvc的父子容器的关系

首先,必须先理解spring在web容器的是如何运行的。  1 对于一个web应用,当其部署在web容器上时,web容器就会给其提供一个全局的上下文环境ServletContext. 这个上下文环...
  • JJ_nan
  • JJ_nan
  • 2017-03-24 16:46:54
  • 1647

Spring、SpringMVC父子容器关系浅析

浅析配置文件:web.xml ... contextConfigLocation classpath:spring/applicationContext.xml ...
  • wuseyukui
  • wuseyukui
  • 2016-11-02 17:38:30
  • 3321

spring和springmvc父子容器的理解

这篇博客写一下对spring和springmvc父子容器的理解。 一、首先明确: (1)spring是一个大的父容器,springmvc是其中的一个子容器。父容器不能访问子容器对象,但是子容器可以访问...
  • zlj1217
  • zlj1217
  • 2017-04-09 21:09:51
  • 1205

spring和springmvc父子容器的关系

大家都知道,在spring的配置中要分开配置service层的注解扫描,以及springmvc变现层的注解扫描,如下: 那么,问题来了,为什么不可以直接在spring的service...
  • LemonTreey
  • LemonTreey
  • 2016-11-08 10:32:46
  • 2434

SpringMVC上下文父子容器

在SpringMVC的启动依赖Spring框架,有时候我们在启动SpringMVC环境的时候,如果配置不当的话会造成一些不可预知的结果。下面主要介绍一下SpringMVC环境启动的时候context的...
  • dreamsunday
  • dreamsunday
  • 2016-05-22 09:34:25
  • 5690

Spring和springmvc父子容器注解扫描问题详解

在springmvc中,我们经常配置两个xml,一个spring专属,一个springMVC专属,在这两个xml中我们都可以配置bean的自动扫描。 一般我们在spring.xml中不扫描@Cont...
  • u011217058
  • u011217058
  • 2017-07-25 15:32:36
  • 1158

spring 父子容器的概念,入门博客推荐。必看

看这篇。http://elf8848.iteye.com/blog/875830/ -------------------------------------------------20160519...
  • wabiaozia
  • wabiaozia
  • 2016-04-07 13:49:34
  • 2143
收藏助手
不良信息举报
您举报文章:spring和springMVC父子容器的原理
举报原因:
原因补充:

(最多只允许输入30个字)