springmvc源码分析
一直对springmvc源码感兴趣,就看了下源码,写下这偏文章,当做笔记
springmvc主要是完成逻辑方法的映射和参数绑定工作,它的初始化是随着Tomcat启动时,调用HttpServlet进行。
通过DispatcherServlet会创建一个XmlWebApplicationContext,然后进行Controller等Bena的扫描和实例化,然后
调用容器的refresh方法进行九大部件的注册
下面贴下流程图:
1.Tomcat启动后,DisparcherServlet的初始化流程
2.RequestMappingHandlerMapping的初始化流程和作用:
它是在实例化后进行映射方法的扫描和注册,然后封装了RequestMappingInfo和MethodHandler方法的映射Map中缓存。RequestMappingInfo的信息一般是对@RequestMapping注解的解析,MethodHandler包含Controller方法的信息和类的一些信息,也包括的参数的类型。
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进行视图跳转