1. 前言

2. 类图

了解DispatcherServlet之前,我们先来了解一下它的类关系图: DispatcherServlet类图

3. 方法跟踪时序图

DispatcherServlet初始化方法跟踪时序图

4. 跟踪过程源码研究

4.1. defaultStrategies初始化

DispatcherServlet有一个静态类函数,负责从属性文件中加载默认的策略实现,静态函数和属性文件如下:

4.1.1. DispatcherServlet#static

private static final String DEFAULT_STRATEGIES_PATH = "DispatcherServlet.properties";

static {
    // Load default strategy implementations from properties file.
    // This is currently strictly internal and not meant to be customized
    // by application developers.
    try {
        ClassPathResource resource = new ClassPathResource(DEFAULT_STRATEGIES_PATH, DispatcherServlet.class);
        defaultStrategies = PropertiesLoaderUtils.loadProperties(resource);
    }
    catch (IOException ex) {
        throw new IllegalStateException("Could not load 'DispatcherServlet.properties': " + ex.getMessage());
    }
}

4.1.2. DispatcherServlet.properties

# Default implementation classes for DispatcherServlet's strategy interfaces.
# Used as fallback when no matching beans are found in the DispatcherServlet context.
# Not meant to be customized by application developers.

org.springframework.web.servlet.LocaleResolver=org.springframework.web.servlet.i18n.AcceptHeaderLocaleResolver

org.springframework.web.servlet.ThemeResolver=org.springframework.web.servlet.theme.FixedThemeResolver

org.springframework.web.servlet.HandlerMapping=org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping,\
    org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping

org.springframework.web.servlet.HandlerAdapter=org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter,\
    org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter,\
    org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter

org.springframework.web.servlet.HandlerExceptionResolver=org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerExceptionResolver,\
    org.springframework.web.servlet.mvc.annotation.ResponseStatusExceptionResolver,\
    org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver

org.springframework.web.servlet.RequestToViewNameTranslator=org.springframework.web.servlet.view.DefaultRequestToViewNameTranslator

org.springframework.web.servlet.ViewResolver=org.springframework.web.servlet.view.InternalResourceViewResolver

org.springframework.web.servlet.FlashMapManager=org.springframework.web.servlet.support.SessionFlashMapManager

根据约定优于配置原则,Spring默认提供了一系列的策略实现类,并配置在了属性文件中,如处理请求映射的HandlerMapping等;

4.2. Servlet初始化init方法

DispatcherServlet本质上是继承的HttpServlet类,一个Servlet从创建到销毁主要有三个生命周期方法:initdoServicedestroyDispatcherServlet也不例外,其init方法负责初始化ServletdoService负责处理http请求,这里,我们先看一下init方法如何初始化DispatcherServlet,至于doService方法如何处理http请求,后面再具体研究。

4.2.1. HttpServletBean#init

DispatcherServlet创建之后,调用其init方法,此方法在其父类的HttpServletBean中实现,此方法也是DispatcherServlet的入口方法:

@Override
    public final void init() throws ServletException {

    // Set bean properties from init parameters.
    // 省略

    // Let subclasses do whatever initialization they like.
    initServletBean();

}

此方法主要完成两件事:

  1. 初始化参数
  2. 调用子类的initServletBean方法做初始化;

4.2.2. FrameworkServlet#initServletBean

@Override
protected final void initServletBean() throws ServletException {
    // 省略日志代码。。。

    try {
        this.webApplicationContext = initWebApplicationContext();
        initFrameworkServlet();
    }
    // 省略catch、日志代码
}

我们知道,SpringMVC底层也是使用的Spring的核心功能,即ioc容器来做bean的管理。FrameworkServlet类中有一个很重要的变量:webApplicationContext,此变量即为Spring Web容器:

private WebApplicationContext webApplicationContext;

而方法initWebApplicationContext()用来进行容器的初始化。我们跟踪一下容器如何做得初始化。

protected WebApplicationContext createWebApplicationContext(ApplicationContext parent) {
    Class<?> contextClass = getContextClass();
    // 省略部分代码
    ConfigurableWebApplicationContext wac =
            (ConfigurableWebApplicationContext) BeanUtils.instantiateClass(contextClass);

    wac.setEnvironment(getEnvironment());
    wac.setParent(parent);
    wac.setConfigLocation(getContextConfigLocation());

    configureAndRefreshWebApplicationContext(wac);

    return wac;
}

initWebApplicationContext最终调用了createWebApplicationContext方法来进行webAplicationContext的初始化,wac是通过contextClass变量进行的实例化:

public static final Class<?> DEFAULT_CONTEXT_CLASS = XmlWebApplicationContext.class;

private Class<?> contextClass = DEFAULT_CONTEXT_CLASS;

public Class<?> getContextClass() {
    return this.contextClass;
}

此变量是写死的XmlWebApplicationContext.class,到这里,我们知道,spring mvc中的容器是使用的XmlWebApplicationContext进行的实例化。

4.2.3. configureAndRefreshWebApplicationContext

在创建了webApplicationContext对象之后,调用了configureAndRefreshWebApplicationContext()方法,此方法负责配置及刷新容器:

protected void configureAndRefreshWebApplicationContext(ConfigurableWebApplicationContext wac) {
    //省略部分代码

    wac.setServletContext(getServletContext());
    wac.setServletConfig(getServletConfig());
    wac.setNamespace(getNamespace());
    wac.addApplicationListener(new SourceFilteringListener(wac, new ContextRefreshListener()));

    // The wac environment's #initPropertySources will be called in any case when the context
    // is refreshed; do it eagerly here to ensure servlet property sources are in place for
    // use in any post-processing or initialization that occurs below prior to #refresh
    ConfigurableEnvironment env = wac.getEnvironment();
    if (env instanceof ConfigurableWebEnvironment) {
        ((ConfigurableWebEnvironment) env).initPropertySources(getServletContext(), getServletConfig());
    }

    postProcessWebApplicationContext(wac);
    applyInitializers(wac);
    wac.refresh();
}

我们可以看到,最后一句wac.refresh();其实调用了AbstractApplicationContext容器的模板方法refresh,到这里,我们应该比较熟悉了,所有的容器类都是使用的此方法进行的初始化。而到此为止,DispatcherServlet的初始化看上去亦完成了。

通过查看debug日志,我们发现,在Servlet初始化完成之后,其实所有的url已经和Controller#method映射完成了,到目前为止我们没有看到映射的代码,这其实就涉及到spring的一个比较重要的概念,即上面代码中的wac.addApplicationListener(new SourceFilteringListener(wac, new ContextRefreshListener()));这行代码。 应用监听器是spring提供的一系列扩展接口的一种,下一章我们重要研究XmlWebApplicationContext的refresh执行过程,包括BeanPostProcessor后处理器、事件等;

Copyright © wychuan.com 2017 all right reserved,powered by Gitbook该文件修订时间: 2018-01-09 08:05:07

results matching ""

    No results matching ""