springmvc源码分析

一直对springmvc源码感兴趣,就看了下源码,写下这偏文章,当做笔记

     springmvc主要是完成逻辑方法的映射和参数绑定工作,它的初始化是随着Tomcat启动时,调用HttpServlet进行。

     通过DispatcherServlet会创建一个XmlWebApplicationContext,然后进行Controller等Bena的扫描和实例化,然后

     调用容器的refresh方法进行九大部件的注册

下面贴下流程图:

1.Tomcat启动后,DisparcherServlet的初始化流程

springmvc源码分析

2.RequestMappingHandlerMapping的初始化流程和作用:

     它是在实例化后进行映射方法的扫描和注册,然后封装了RequestMappingInfo和MethodHandler方法的映射Map中缓存。RequestMappingInfo的信息一般是对@RequestMapping注解的解析,MethodHandler包含Controller方法的信息和类的一些信息,也包括的参数的类型。

 springmvc源码分析

3. 调用MethodHandler方法的代码如下:org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter#invokeHandlerMethod

@Nullable
protected ModelAndView invokeHandlerMethod(HttpServletRequest request,
      HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {

   ServletWebRequest webRequest = new ServletWebRequest(request, response);
   try {
      WebDataBinderFactory binderFactory = getDataBinderFactory(handlerMethod);//初始化initBinder注解的方法然后缓存
      ModelFactory modelFactory = getModelFactory(handlerMethod, binderFactory);//处理@ModelAttribute的所有方法,过程和上面类似

      ServletInvocableHandlerMethod invocableMethod = createInvocableHandlerMethod(handlerMethod);
      if (this.argumentResolvers != null) {
         invocableMethod.setHandlerMethodArgumentResolvers(this.argumentResolvers);
      }
      if (this.returnValueHandlers != null) {
         invocableMethod.setHandlerMethodReturnValueHandlers(this.returnValueHandlers);
      }
      invocableMethod.setDataBinderFactory(binderFactory);
      invocableMethod.setParameterNameDiscoverer(this.parameterNameDiscoverer);

      ModelAndViewContainer mavContainer = new ModelAndViewContainer();
      mavContainer.addAllAttributes(RequestContextUtils.getInputFlashMap(request));
      modelFactory.initModel(webRequest, mavContainer, invocableMethod);//有调用ModelAttrbute的过程会取出方法的值和注解中的value作为name存储到model中
      mavContainer.setIgnoreDefaultModelOnRedirect(this.ignoreDefaultModelOnRedirect);

      AsyncWebRequest asyncWebRequest = WebAsyncUtils.createAsyncWebRequest(request, response);
      asyncWebRequest.setTimeout(this.asyncRequestTimeout);

      WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
      asyncManager.setTaskExecutor(this.taskExecutor);
      asyncManager.setAsyncWebRequest(asyncWebRequest);
      asyncManager.registerCallableInterceptors(this.callableInterceptors);
      asyncManager.registerDeferredResultInterceptors(this.deferredResultInterceptors);

      if (asyncManager.hasConcurrentResult()) {
         Object result = asyncManager.getConcurrentResult();
         mavContainer = (ModelAndViewContainer) asyncManager.getConcurrentResultContext()[0];
         asyncManager.clearConcurrentResult();
         LogFormatUtils.traceDebug(logger, traceOn -> {
            String formatted = LogFormatUtils.formatValue(result, !traceOn);
            return "Resume with async result [" + formatted + "]";
         });
         invocableMethod = invocableMethod.wrapConcurrentResult(result);
      }

      invocableMethod.invokeAndHandle(webRequest, mavContainer);
      if (asyncManager.isConcurrentHandlingStarted()) {
         return null;
      }

      return getModelAndView(mavContainer, modelFactory, webRequest);
   }
   finally {
      webRequest.requestCompleted();
   }
}

4.视图渲染的意思:

把ModelAttribute的一些属性copy到Request中的attribute中的过程,然后调用底层的request进行视图跳转 

感觉阅读源码一定要用好工具,然后花些时间去debug,spring的源码封装的层次很深,需要有些耐心一点一点的去研究!不足之处希望大家及时指正!!!!