美文网首页我的文章-SpringMVC
SpringMVC 容器初始化过程

SpringMVC 容器初始化过程

作者: 飞翔的鲲 | 来源:发表于2018-08-07 16:24 被阅读54次

    时序图


    • 初始化过程


      image.png
    • SpringMVC容器初始化
      1.系统启动时,调用initWebApplicationContext()方法,初始化容器,将bean都放入容器中。
      2.生成XmlWebApplicationContext是在这个方法中configureAndRefreshWebApplicationContext()。
      3.最后调用XmlWebApplicationContext的refresh()方法初始化容器,就是使用的Spring的方法,和Spring初始化一样。


      image.png
        protected void configureAndRefreshWebApplicationContext(ConfigurableWebApplicationContext wac) {
            if (ObjectUtils.identityToString(wac).equals(wac.getId())) {
                if (this.contextId != null) {
                    wac.setId(this.contextId);
                } else {
                    wac.setId(ConfigurableWebApplicationContext.APPLICATION_CONTEXT_ID_PREFIX + ObjectUtils.getDisplayString(this.getServletContext().getContextPath()) + '/' + this.getServletName());
                }
            }
    
            wac.setServletContext(this.getServletContext());
            wac.setServletConfig(this.getServletConfig());
            wac.setNamespace(this.getNamespace());
            wac.addApplicationListener(new SourceFilteringListener(wac, new FrameworkServlet.ContextRefreshListener(null)));
            ConfigurableEnvironment env = wac.getEnvironment();
            if (env instanceof ConfigurableWebEnvironment) {
                ((ConfigurableWebEnvironment)env).initPropertySources(this.getServletContext(), this.getServletConfig());
            }
    
            this.postProcessWebApplicationContext(wac);
            this.applyInitializers(wac);
            wac.refresh();
        }
    
    • doGet调用过程


      image.png
    • doDispatch调用过程(SpringMVC核心)
      最后将view渲染到response里了


      image.png

    源码分析

    1. DispatcherServlet是SpringMVC的核心,整个过程都是使用这个类完成。这个类的核心方法为doDispatch().
    protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
            HttpServletRequest processedRequest = request;
            HandlerExecutionChain mappedHandler = null;
            boolean multipartRequestParsed = false;
            WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
    
            try {
                try {
                    ModelAndView mv = null;
                    Object dispatchException = null;
    
                    try {
                        processedRequest = this.checkMultipart(request);
                        multipartRequestParsed = processedRequest != request;
                        mappedHandler = this.getHandler(processedRequest);
                        if(mappedHandler == null || mappedHandler.getHandler() == null) {
                            this.noHandlerFound(processedRequest, response);
                            return;
                        }
    
                        HandlerAdapter ha = this.getHandlerAdapter(mappedHandler.getHandler());
                        String method = request.getMethod();
                        boolean isGet = "GET".equals(method);
                        if(isGet || "HEAD".equals(method)) {
                            long lastModified = ha.getLastModified(request, mappedHandler.getHandler());
                            if(this.logger.isDebugEnabled()) {
                                this.logger.debug("Last-Modified value for [" + getRequestUri(request) + "] is: " + lastModified);
                            }
    
                            if((new ServletWebRequest(request, response)).checkNotModified(lastModified) && isGet) {
                                return;
                            }
                        }
    
                        if(!mappedHandler.applyPreHandle(processedRequest, response)) {
                            return;
                        }
    
                        mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
                        if(asyncManager.isConcurrentHandlingStarted()) {
                            return;
                        }
    
                        this.applyDefaultViewName(processedRequest, mv);
                        mappedHandler.applyPostHandle(processedRequest, response, mv);
                    } catch (Exception var20) {
                        dispatchException = var20;
                    } catch (Throwable var21) {
                        dispatchException = new NestedServletException("Handler dispatch failed", var21);
                    }
    
                    this.processDispatchResult(processedRequest, response, mappedHandler, mv, (Exception)dispatchException);
                } catch (Exception var22) {
                    this.triggerAfterCompletion(processedRequest, response, mappedHandler, var22);
                } catch (Throwable var23) {
                    this.triggerAfterCompletion(processedRequest, response, mappedHandler, new NestedServletException("Handler processing failed", var23));
                }
    
            } finally {
                if(asyncManager.isConcurrentHandlingStarted()) {
                    if(mappedHandler != null) {
                        mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response);
                    }
                } else if(multipartRequestParsed) {
                    this.cleanupMultipart(processedRequest);
                }
    
            }
        }
    
    1. 真正处理Controller里方法的是invokeHandlerMethod()方法,返回ModelAndView对象。比如RequestMappingHandlerAdapter里面的这个方法。
    protected ModelAndView invokeHandlerMethod(HttpServletRequest request, HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {
            ServletWebRequest webRequest = new ServletWebRequest(request, response);
    
            Object result;
            try {
                WebDataBinderFactory binderFactory = this.getDataBinderFactory(handlerMethod);
                ModelFactory modelFactory = this.getModelFactory(handlerMethod, binderFactory);
                ServletInvocableHandlerMethod invocableMethod = this.createInvocableHandlerMethod(handlerMethod);
                invocableMethod.setHandlerMethodArgumentResolvers(this.argumentResolvers);
                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);
                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()) {
                    result = asyncManager.getConcurrentResult();
                    mavContainer = (ModelAndViewContainer)asyncManager.getConcurrentResultContext()[0];
                    asyncManager.clearConcurrentResult();
                    if(this.logger.isDebugEnabled()) {
                        this.logger.debug("Found concurrent result value [" + result + "]");
                    }
    
                    invocableMethod = invocableMethod.wrapConcurrentResult(result);
                }
    
                invocableMethod.invokeAndHandle(webRequest, mavContainer, new Object[0]);
                if(!asyncManager.isConcurrentHandlingStarted()) {
                    ModelAndView var15 = this.getModelAndView(mavContainer, modelFactory, webRequest);
                    return var15;
                }
    
                result = null;
            } finally {
                webRequest.requestCompleted();
            }
    
            return (ModelAndView)result;
        }
    
    1. 渲染使用View的render()方法,真正执行的是具体的视图渲染。比如FreeMarkerView的doRender()方法。
      渲染就是将model中的值放到request中,使用request.setAttribute()。

    相关文章

      网友评论

        本文标题:SpringMVC 容器初始化过程

        本文链接:https://www.haomeiwen.com/subject/axsavftx.html