原帖地址:http://blog.csdn.net/roderick2015/article/details/52846240,转载请注明。
我们先回顾下在Web应用中构建SpringMVC框架的大体流程:
1.使用Maven等工具引入依赖(依赖的jar包还不少)。
2.在web.xml中配置DispatcherServlet。
3.创建spring-mvc.xml文件,在这里写上我们对SpringMVC的定制化配置(或者使用注解类的方式)。
4.编写Controller类,使用注解的方式指定与URL对应的处理方法(当然你可能还得准备JSP之类的页面)。
5.发布到Web容器(本帖使用的是Tomcat)并启动。
整个流程并不复杂,但每个步骤所涉及的东西比较多,一不小心配错可就糟糕了。但这参与感十足的配置方式除了它的灵活性外,也能让我们更加清楚框架在为我们服务之前,到底做了哪些事情,接下来我们就到源码中去看看SpringMVC的核心入口类DispatcherServlet在Web容器启动后做了哪些准备。
从DispatcherServlet的名字可以知道它是个Servlet,我们看下它在web.xml中的具体配置,代码如下所示。
<servlet>
//servlet的名字
<servlet-name>dispatcher</servlet-name>
//指定具体的类
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
//以类似HashMap中key和value的方式给servlet配置一些参数信息
<init-param>
//指定context配置文件的路径
<param-name>contextConfigLocation</param-name>
<param-value>classpath:/spring-mvc.xml</param-value>
</init-param>
<init-param>
//不要在意这个参数,帖子后面会提到的
<param-name>publishContext</param-name>
<param-value>true</param-value>
</init-param>
//大于或等于1表示web容器在启动的时候就会调用,值越大优先级越高
//0或-1表示在第一次被使用的时候才会调用
<load-on-startup>1</load-on-startup>
</servlet>
//url路径映射
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
接着看它的继承体系,如下图所示。
图中可以很清晰地看到DispatcherServlet的继承主线是比较单一的:DispatcherServlet —> FrameworkServlet —> HttpServletBean,我们主要分析这三个类,后面的HttpServlet到Servlet接口属于Java的Servlet原生代码,其中GenericServlet也参与了初始化,整个初始化流程如下图所示。
声明:本帖所示的代码一律省略源码中的log日志输出,以精简阅读。
在 Tomcat启动时会加载应用的Web.xml文件,这时就会扫描到DispatchServlet,然后调用init方法进行初始化(就是Servlet接口的init方法嘛),该方法的具体实现在DispatchServlet的父类GenericServlet中,也是DispatchServlet初始化的入口。
GenericServlet
GenericServlet初始化的时候就干了两件事:
1.接收Tomcat传过来的ServletConfig。
2.调用空方法init,供子类覆写实现后续的初始化。
public void init(ServletConfig config) throws ServletException {
this.config = config;
this.init();
}
public void init() throws ServletException {
}
这里看下config里面到底装了什么东西,如下图所示。
StandardWrapper和ApplicationContextFacade都是Tomcat中的对象,本帖不作详细说明,只需要知道ApplicationContextFacade里放的是整个Web应用的上下文信息,StandardWrapper则是针对DispatchServlet的,它两的作用域不同。如下图所示,可以看到我们在Web.xml文件中配置的相关数据。
HttpServletBean
接着HttpServletBean作为子类覆写了GenericServlet的init方法,代码如下所示。
@Override
public final void