`
hotforcc
  • 浏览: 61086 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

Spring DispatcherServlet MVC 源码分析(Webapplicationcontext的生成)

阅读更多

<servlet></servlet>

xml 代码
 
  1. <servlet>  
  2.     <servlet-name>Dispatcher</servlet-name>  
  3.     <servlet-class>  
  4.         org.springframework.web.servlet.DispatcherServlet  
  5.     </servlet-class>  
  6.     <init-param>  
  7.         <param-name>contextConfigLocation</param-name>  
  8.         <param-value>/WEB-INF/Config.xml</param-value>  
  9.     </init-param>  
  10.     <load-on-startup>1</load-on-startup>  
  11. </servlet>  

由此,我们可知,web container把所有的请求都交给DispatcherServlet也就是 org.springframework.web.servlet.dispatcherservlet来处理了。dispatcherservlet是研究springframework mvc的关键类,在你的spring 工程中打开该类的源代码吧。<o:p></o:p>

<o:p></o:p>在你spring工程中你可以看到,dispatcherservlet的父类是frameworkservlet,frameworkservlet的父类 httpservletbean,httpservletbean的父类是httpservlet,因此dispatcherservlet本质上是个 httpservlet.web.xml中的<load-on-startup>2</load-on-startup>表明,jsp container 在启动的时候就会生成dispatcherservlet,自然会执行其init()方法了。从 dispatcherservlet的源代码来看,他并没有直接覆盖父类的init(),我们再来看看frameworkservletinit(), 呵呵,frameworkservlet也没有,一路追溯上去,终于在httpservletbean类中找到了init(),该方法中调用 initservletbean();再看frameworkservletinitservletbean()<o:p></o:p>

<o:p> </o:p>

里面关键的有2:<o:p></o:p>

java 代码
 
  1. 1.this.webapplicationcontext = initwebapplicationcontext();  
  2. 2.initframeworkservlet();  

<o:p></o:p>

<o:p></o:p>我们先来看第一句 initwebapplicationcontext();在开始研究这个方法之前,我们得了解一下spring <o:p></o:p>webapplicationcontext是个什么东西,从spring-reference.pdf的第九章的得知,每一个 dispatcherservlet都有它的webapplicationcontext,每一个webapplicationcontext都是一个applicationcontext,自然也是一个beanfactory,源码分析<o:p></o:p>

<o:p> </o:p>

java 代码
 
  1. public interface WebApplicationContext extends ApplicationContext {};//WebApplicationContext 扩展ApplicationContext  
  2. public interface ApplicationContext extends ListableBeanFactory, HierarchicalBeanFactory,  
  3.         MessageSource, ApplicationEventPublisher, ResourcePatternResolver  
  4. //ApplicationContext扩展了BeanFactory  

<o:p></o:p>

<o:p> </o:p>

而且,每一个webapplicationcontext有一个 parent webapplicationcontext,这个parent是整个web applicationcontext,自然也是个 beanfactory,这个parent的内容默认是从/web-inf/applicationcontext.xml文件装载, dispatcherservlet自己的webapplicationcontext则是从一个叫xxxx-servlet.xml的文件装载的。 xxxx就是在web.xmldispatcherservlet定义的servlet-name.<o:p></o:p>明白了这层关系,我们再来看 initwebapplicationcontext(),它所做的无非就是生成dispatcherservlet webapplicationcontext,同时设置好它的相关属性。我们先来看看它的parent属性是如何设置的。然后再看他自己的 webapplicationcontext内容是如何从xxxx-serlvet.xml里面装载的。<o:p></o:p>

<o:p></o:p>例如 <o:p></o:p>

<servlet><o:p></o:p></servlet>

<servlet-name>

xml 代码
 
  1. <servlet>  
  2. <servlet-name>Dispatcher</servlet-name>  
  3. <servlet-class>  
  4. org.springframework.web.servlet.DispatcherServlet  
  5. </servlet-class>  
  6. <init-param>  
  7. <param-name>contextConfigLocation</param-name>  
  8. <param-value>/WEB-INF/Config.xml</param-value>  
  9. </init-param>  
  10. </servlet>  
  11. <servlet-mapping>  
  12. <servlet-name>Dispatcher</servlet-name>  
  13. <url-pattern>*.do</url-pattern>  
  14. </servlet-mapping>  

<o:p>

initwebapplicationcontext()中有这么一句:<o:p></o:p>

webapplicationcontext parent  = webapplicationcontextutils.getwebapplicationcontext(servletcontext);<o:p></o:p>

然后在createwebapplicationcontext()方法中有这么一句:wac.setparent(parent);由此可见, dispatcherservletwebapplicationcontextparent是在 initwebapplicationcontext()中得到,然后在createwebapplicationcontext()方法中设置的。好奇的你也许会问,这个parent 实例到底是谁生成的呢,和/web-inf/applicationcontext-hibernate.xml文件有什么关系呢.我们现在就来探讨一下这个问题。在spring工程中打开webapplicationcontextutils getwebapplicationcontext()方法中只有那么一句:return (webapplicationcontext) sc.getattribute (webapplicationcontext.root_web_application_context_attribute);也就是说,早就有人在web applicationserlvet context里面设置好了这个属性,dispatcherservlet initwebapplicationcontext()只是利用webapplicationcontextutils servlet context把这个对象按名字检索出来而已。也许你已经按捺不住了,到底是谁设置了这个属性呢。不用急,我们打开web.xml看看,在petclinic servlet的定义之前,还有一个servlet的定义:<o:p></o:p>

<o:p>

java 代码
 
  1. <servlet>  
  2.    <servlet-name>context</servlet-name>  
  3.    <servlet-class>org.springframework.web.context.contextloaderservlet</servlet-class>  
  4.    <load-on-startup>1</load-on-startup>  
  5. </servlet>  

<o:p>

相信聪明的你已经从该servlet的名字和条目前面的注释猜出这个parent,也就是web applicationroot context是由 contextloaderservlet来设置的。没错,从contextloaderservletinit方法中我们可以发现, contextloaderservlet生成一个contextloader,并且调用其initwebapplicationcontext()方法来设置root context。看看contextloader类,我们的答案都找到了。在其initwebapplicationcontext() 中,首先生成一个applicationcontext作为root contextparent,呵呵,在root context之上没有 context了,这个parent自然是null;root context本身则在contextloader createwebapplicationcontext()方法里设置。该方法的步骤如下:<o:p></o:p>

<o:p></o:p>1.看在web.xml有没有定义定制的 context(contextclass参数指出),如果没有的话,<o:p></o:p>

就用xmlwebapplicationcontext类来作为缺省的 context类。在我们的这个petclinic工程里面,没有使用定制的context类,<o:p></o:p>

自然也就是用 xmlwebapplicationcontext类来作为context类了。<o:p></o:p>

2.利用beanutils来生成一个context实例,在这里也就是一个xmlwebapplicationcontext实例。<o:p></o:p>

3.设置parent属性,也就是null;<o:p></o:p>

4.设置servletcontext属性,该属性还是从contextloaderservlet传过来的。<o:p></o:p>

5.web.xml中找到参数contextconfiglocation,作为配置文件的路径。我们在web.xml中定义contextconfiglocation的值是<o:p></o:p>

"/web-inf/applicationcontext-hibernate.xml"<o:p></o:p>

6.利用contextconfiglocation属性指出的xml配置文件中的内容刷新生成xmlwebapplicationcontext实例。<o:p></o:p>

<o:p></o:p>呵呵,到此为止,关于web applicationroot context的出生问题已经搞清楚了,那么到底是谁把这个实例设置为 servlet context的一个attribute的呢@呵呵,聪明的你肯定已经发现了contextloader initwebapplicationcontext方法中有这么一句:webapplicationcontextutils.publishwebapplicationcontext (wac);没错,contextloader正是利用webapplicationcontextutilsroot context绑定为 servlet context的一个属性的。至于这个属性叫什么名字,我想就不用我多说了。之所以让contextloaderservlet load-on-startup=1,就是让这个servlet初始化web applicationroot context属性,绑定到 servlet context.正如web.xml文中的注释指出的一样,如果你使用满足servlet 2.4规范的容器,你就只需在web.xml 中定义一个contextloaderlistener就行了,而不用使用contextloaderservlet<o:p></o:p>

<o:p></o:p>饶了这么大一个圈子,我们才明白了dispatcherservletwebapplicationcontextparent是如何来的。现在该说说dispatcherservletwebapplicationcontext本身是如何设置的了。<o:p></o:p>

<o:p></o:p>现在我们来看看frameworkservletcreatewebapplicationcontext()方法。同contextloader createwebapplicationcontext()类似的步骤。不同之处在于前者含有wac.setnamespace (getnamespace());语句。通过跟踪getnamespace()我们得到frameworkservletnamespace属性其实就是字符串"[servletname]-serlvet"(servletname变量在web.xml中定义,对我们的工程而言就是Dispatcher)<o:p></o:p>

<o:p></o:p>

java 代码
 
  1. public String getNamespace() {  
  2.         return (this.namespace != null) ? this.namespace : getServletName() + DEFAULT_NAMESPACE_SUFFIX;  
  3. }  
  4.   
  5. public static final String DEFAULT_NAMESPACE_SUFFIX = "-servlet";  

<o:p></o:p>

<o:p></o:p>接下来有这么一句:<o:p></o:p>

java 代码
 
  1. if (this.contextconfiglocation != null){  
  2.  wac.setconfiglocations(webapplicationcontextutils.parsecontextconfiglocation(this.contextconfiglocation));  

<o:p></o:p>

<o:p> </o:p>

这个if语句会不会执行呢@也就是说frameworkservlet的私有属性contextconfiglocation是不是为空呢@也就是有没有人给frameworkservlet初始化这个属性呢@答案就在于frameworkservlet的父类httpservletbeaninit() 方法中,里面有这么一句propertyvalues pvs = new servletconfigpropertyvalues (getservletconfig(), this.requiredproperties);仔细研究 servletconfigpropertyvalues()方法就知道,如果你在web.xmldispatcherservlet定义 init-param参数contextconfiglocation的话(形式通常是诸如/web-inf/test-servlet.xml,  /web-inf/myservlet.xml),父类方法init()中就会给frameworkservlet初始化这个属性.<o:p></o:p>

在我们的工程并没有定义这个init-param参数,因此前面所说的if语句不会执行了。也就是frameworkservlet createwebapplicationcontext()方法中的wac只是初始化了属性namespace,而没有初始化 contextconfiglocation.接下来是wac.refresh();通过查看这个方法的源码( xmlwebapplicationcontext类中)我们就知道,在没有给xmlwebapplicationcontext初始化 contextconfiglocation属性的情况下,它会从namespace属性指出的xml配置文件中装载beandefinitions,我们的工程而言就是Dispatcher-servlet.xml文件。<o:p></o:p>

<o:p> </o:p>

至此为止,我们的 webapplicationcontext终于生成了。回到frameworkservletinitwebapplicationcontext ()方法,我们可以发现,


这个生成的webapplicationcontext org.springframework.web.servlet.Frameworkservlet.CONTEXT.key保存在servletcontext里面.<o:p></o:p>

<o:p></o:p>

分享到:
评论
2 楼 liwanfeng 2011-10-13  
看楼上的评价不错,但是格式可能是je改版,现在看格式比较乱啊!实在没心情看了!
1 楼 charles_zuo 2008-05-23  
讲解的很详细,按照LZ的分析看了下源码,条理很清晰,谢谢

相关推荐

    Spring Web MVC外文翻译

    ### Spring Web MVC 外文翻译知识点解析 #### 一、Spring Web MVC介绍 ...特别是 DispatcherServlet 的配置及其与 WebApplicationContext 的交互方式,是深入掌握 Spring Web MVC 不可缺少的一部分。

    Spring源码学习九:DispatcherServlet初始化源码分析1

    Spring源码学习九:DispatcherServlet初始化源码分析1 DispatcherServlet是SpringMVC的核心分发器,它实现了请求分发,是处理请求的入口,本篇将深入源码分析它的初始化过程。 首先,从DispatcherServlet的名称上...

    Spring mvc 教程

    ### Spring MVC 教程知识点详解 #### Spring Web MVC 框架简介 Spring Web MVC 是 Spring Framework 的一个重要组成部分,主要用于构建基于 Java 的 Web 应用程序。它提供了一个灵活且强大的 MVC 实现,使得开发者...

    spring mvc jar包

    3. `org.springframework.web.servlet-3.0.2.RELEASE.jar`:这是 Spring MVC 的核心模块,提供了控制器(Controller)、模型视图(ModelAndView)以及调度器Servlet(DispatcherServlet)等关键组件。...

    spring的mvc.doc

    总结,Spring MVC的执行流程包括初始化阶段(创建`WebApplicationContext`,配置`ServletConfig`和`ServletContext`)和请求处理阶段(通过`DispatcherServlet`接收请求,分发到相应的Controller处理,然后返回响应...

    Spring MVCSpring MVC基础.ppt

    DispatcherServlet也初始化了一个WebApplicationContext,它是Spring容器的一个特殊版本,专门用于Web应用。 2. **IoC(Inversion of Control)容器**:Spring MVC中的Controller组件是JavaBean,它们的实例化、...

    spring mvc

    - DispatcherServlet 是 Spring MVC 的入口点,它负责接收客户端的请求并将其分发到合适的组件进行处理。 **2. HandlerMapping 接口** - **作用**:将 HTTP 请求映射到具体的处理方法上。 - **实现类**: - **...

    Spring MVC总结(一)

    Spring MVC架构与DispatcherServlet配置 Spring MVC是一种流行的基于Java的Web应用框架,它提供了一个灵活的架构来开发Web应用程序。在本文中,我们将对Spring MVC的架构和DispatcherServlet的配置进行总结。 ...

    Spring源代码解析(四):Spring_MVC.doc

    在Spring源代码解析的第四部分中,我们将重点关注DispatcherServlet的初始化过程,它是Spring MVC的核心组件。 DispatcherServlet是一个特殊的Servlet,它负责接收HTTP请求,并根据请求映射到相应的处理器...

    Spring MVC 4.2.4.RELEASE 中文文档v

    文档中提到的 DispatcherServlet 是 Spring MVC 中的一个核心组件,它负责将请求分发给不同的处理器,并提供了一种简单而有效的方式来定制 Web 应用程序的行为。DispatcherServlet 的配置、处理流程以及 ...

    Spring MVC 4.2.4.RELEASE 中文文档

    DispatcherServlet 的处理流程则解释了请求在 Spring MVC 中的处理过程,包括请求的接收、处理以及响应的生成。 控制器的实现部分通过使用@Controller 注解定义了一个控制器类,并通过@RequestMapping 注解映射请求...

    spring-webmvc.src.zip

    通过分析这些源码,我们可以了解到Spring Web MVC如何处理HTTP请求,如何将请求映射到控制器,如何处理异常,以及如何渲染视图。它提供的注解驱动和依赖注入能力使得开发更加简洁高效。同时,Spring Web MVC还提供了...

    spring-mvc-documentation-linesh-translation

    - **WebApplicationContext**: 这是 Spring Web MVC 的应用上下文,用于管理 Web 层的 Bean 和配置。 #### 默认配置 - **默认的DispatcherServlet配置**: DispatcherServlet 的默认配置包括自动检测控制器类、注册...

    SpringMVC源码剖析(二)- DispatcherServlet的前世今生1

    为此,Spring MVC引入了WebApplicationContext接口,特别是XmlWebApplicationContext,它是专门为Web应用程序设计的IoC上下文。它能够加载Web相关的配置,并在Servlet容器启动时初始化Spring MVC的组件,如...

    spring-web.jar spring-webmvc.jar

    1. **DispatcherServlet**:作为Spring MVC的核心,`DispatcherServlet`负责拦截所有到达的HTTP请求,然后根据请求映射找到合适的处理器(控制器)进行处理。 2. **控制器**:开发者可以定义控制器类,这些类处理...

    Spring-5.1.5源码

    4. **Spring MVC**:`ContextLoaderListener`初始化的ApplicationContext与Spring MVC的DispatcherServlet所使用的ApplicationContext不同。前者是全局的父上下文,而后者是用于处理HTTP请求的子上下文。两者之间...

    05-Spring MVC面试题.docx

    Spring MVC框架详解 Spring MVC是基于Java的实现了MVC设计模式的请求驱动类型的轻量级Web...WebApplicationContext是Spring MVC的核心组件之一,它提供了一个ApplicationContext的实现,用于管理Web应用程序的资源。

    Spring-的MVC框架PPT课件.ppt

    12. Spring Bean的生命周期可以被限制在当前的HTTP Request或者HTTP Session:准确的说,这并非Spring MVC框架本身特性,而应归属于Sping MVC使用的WebApplicationContext容器。 13. DispatcherServlet的功能:...

    spring mvc学习笔记

    在 Spring MVC 中,通常会使用一个根 ApplicationContext 和一个或多个 DispatcherServlet 的局部 ApplicationContext。 - WebApplicationContext 与普通的 ApplicationContext 相比,具有更多的灵活性和扩展性,...

Global site tag (gtag.js) - Google Analytics