SpringMVC 源码分析

发表于 2023-03-05

概述

Sping MVC 名字为 Spring Web MVC,是 Spring 中的一个模块,基于 Servlet API 构建,同时使用 MVC 的架构模式。

MVC 架构

模型(Model)

模型封装了数据及对数据的操作,也就是提供数据。

视图(View)

视图是将模型提供的数据展示出来,没有业务处理逻辑。

控制器(Controller)

控制器用于控制程序的流程,例如指定某个模型的数据展示到某个视图中。 MVC

Spring MVC 流程

  • 前端控制器(DispatcherServlet)
    • 请求到达 DispatcherServlet 并完成请求的分发。
  • 处理器映射器(HandlerMapping)
    • 根据请求地址匹配处理器,并构建返回整个请求的执行链(HandlerExecutionChain)。
  • 处理器适配器(HandlerAdaptor)
    • 进行执行器(Handler)的调用,不同的适配器用于执行不同类型的执行链。
  • 执行器(Handler)
    • 业务逻辑,我们编写的 Controller 就是执行器。返回执行结果(ModelAndView)。
  • 视图解析器(ViewResolver)
    • 解析视图名称获取对应的视图对象(View)。
  • 最后视图(View)将数据渲染成页面展示给用户。

SpringMVC

源码重点标记

到达前端控制器(DispatcherServlet)的逻辑处理方法 doDispatch

protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
    // 从处理器映射器获取处理器执行链(HandlerExecutionChain)
    mappedHandler = getHandler(processedRequest);
    // 根据处理器类型获取处理器适配器(HandlerAdaptor)
    HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
    // 执行 Spring 拦截器的 preHandle 方法
    mappedHandler.applyPreHandle(processedRequest, response)
    // 通过处理器适配器(HandlerAdaptor)执行处理器
    mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
    // 执行 Spring 拦截器的 postHandle 方法
    mappedHandler.applyPostHandle(processedRequest, response, mv);
    // 解析视图,渲染视图
    processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
}

处理器适配器(HandlerAdaptor)执行处理器

以 RequestMappingHandlerAdapter 为例,再方法 handleInternalinvokeHandlerMethod 执行参数解析,处理器执行。

protected ModelAndView invokeHandlerMethod(HttpServletRequest request, HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {
    // 执行处理器(完成参数解析和具体 Controller 调用)
    invocableMethod.invokeAndHandle(webRequest, mavContainer);
    // 返回 ModelAndView
    return getModelAndView(mavContainer, modelFactory, webRequest);
}

SpringMVC 容器初始化

在前端控制器(DispatcherServlet)的 onRefresh 方法进行 SpringMVC 的初始化。

protected void initStrategies(ApplicationContext context) {
    // 完成各种解析器的构建
	initMultipartResolver(context);
	initLocaleResolver(context);
	initThemeResolver(context);
    // 完成映射器的构建,例如 /user ---> UserController.list
	initHandlerMappings(context);
    // 完成适配器的构建,例如 RequestMappingHandlerAdapter
	initHandlerAdapters(context);
	initHandlerExceptionResolvers(context);
	initRequestToViewNameTranslator(context);
    // 视图解析器
	initViewResolvers(context);
	initFlashMapManager(context);
}

SpringMVC 与 Spring 的父子容器关系

SpringMVC 拥有一个独立的子容器。

在 SpringMVC 中,拿取容器时优先从 SpringMVC 的容器中拿取,如果没有再到 Spring 容器中拿取。

因为这个特性,SpringMVC 可以在 SpringMVC 内部覆盖掉 Spring 容器内的实现 Bean。