Jaccard聚类Jaccard聚类12-22 11:10

SpringMVC源码分析-DispatcherServlet实例化干了些什么

【推荐】2019 Java 开发者跳槽指南.pdf(吐血整理) >>>

上一篇:SpringMVC启动与Spring启动差异分析

阅读这篇文章之前,请先按照模拟SpringBoot编写一个嵌套Tomcat的工具类(方便调试)完成环境的搭建

思考

在开始看源码之前先做一下思考,比如:

1.SpringMVC既然能从Tomcat哪里接收请求,那么SpringMVC一定是提供了一个Servlet的,而且是由这个Servlet完成所有的请求和响应。

2.既然这个Servlet可以提供非常多的功能,而且和Spring相关,那么它应该持有某一种Spring的XxxApplicationContext

3.有了Context,SpringMVC是不是还提供了非常多默认的类去实现复杂的功能,比如参数解析、参数绑定、返回值解析、视图解析等等

 

有了上面的问题,下面带着问题去一个个验证。。。

通过官方文档或者百度或者自己开发经验应该知道有DispatcherServlet这个类。。。。是的,它就是SpringMVC传世纪的类,由它打通tomcat和Spring容器,并让我们的Bean拥有Spring容器丰富多彩功能的权利。

类结构图

那么先分析DispacherServlet的类结构图

可以看到它是Servlet,ApplicationContextAware,EnvironmentAware的子类,那么应该有一下几个特性:

1.能被Tomcat识别与调用,调用的时候会先调用init方法,再调用doXxx方法

2.可以在DispatcherServlet中轻松的获取Context和Environment对象,而且由Spring完成它的实例化(尚待证实,等后面看SpringBoot源码来确认)

源码分析

套路分析:类被实例化之前会先加载,类加载的时候会执行类变量初始化、静态块。所以先看看DispatcherServlet及其父类是否有静态块要执行。。。答案是有

DispatcherServlet的静态块

	static {
		// Load default strategy implementations from properties file.
		// This is currently strictly internal and not meant to be customized
		// by application developers.
		/**
		 * 从DispatcherServlet.properties(此文件在webmvc工程下)当中加载默认的strategy(有道翻译:策略)
		 * SpringMVC官方说:这些类是核心的东西,不允许让普通开发者进行自定义,当然觉得自己牛逼也是可以上
		 */
		try {
			/**
			 * 将在DispatcherServlet.class路径下的DispatcherServlet.properties文件包装到一个ClassPathResource当中
			 */
			ClassPathResource resource = new ClassPathResource(DEFAULT_STRATEGIES_PATH, DispatcherServlet.class);
			/**
			 * 从DispatcherServlet.properties文件中把配置信息加载为Properties对象,里面包含了如下几大部分
			 * LocaleResolver/ThemeResolver/HandlerMapping/HandlerAdapter/HandlerExceptionResolver/RequestToViewNameTranslator/
			 * ViewResolver/FlashMapManager
			 */
			defaultStrategies = PropertiesLoaderUtils.loadProperties(resource);
		}
		catch (IOException ex) {
			throw new IllegalStateException("Could not load '" + DEFAULT_STRATEGIES_PATH + "': " + ex.getMessage());
		}
	}

简单说明一下:

DispatcherServlet.properties当中配置的类都是非常重要的,不要动它们,它们最终都是有Spring完成实例化,所以我们可以写XxxPostProcessor对它们的实例化进行干预,实现一些自定义的功能。

看看配置文件里面的内容,时刻牢记一点,它们很重要,后面DEBUG看到的类几乎都是通过它们带出来的,因为实例化它们的时候,由会默认弄出很多resolver出来。然后根据不同参数去匹配不同的resolver完成入参、出参、映射等等功能。

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.method.annotation.RequestMappingHandlerMapping,	org.springframework.web.servlet.function.support.RouterFunctionMapping

org.springframework.web.servlet.HandlerAdapter=org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter,	org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter,	org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter,	org.springframework.web.servlet.function.support.HandlerFunctionAdapter


org.springframework.web.servlet.HandlerExceptionResolver=org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExceptionResolver,	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

另外还设置了很多类变量的默认值,在此不去分析每一个变量的作用,工作量太庞大了。

DispatcherSerlvet实例化

构造方法的执行与成员变量初始化

构造方法

	public DispatcherServlet(WebApplicationContext webApplicationContext) {
		super(webApplicationContext);
		setDispatchOptionsRequest(true);
	}

将Spring的上下文与DispatcherServlet关联起来,并且将dispatchOptionsRequest设置为true,它的作用是开启Servlet是否可以处理http的options

 

下一篇:SpringMVC源码分析-DispatcherServlet的Init

程序之家二维码

小额赞赏

000
评论