Spring源码分析-MVC模块

初始化阶段 ---> 运行(调用)阶段

 

源码分析

一、初始化阶段

1. 根据配置得知,在DispatcherServlet里没找到init方法,然后在它的父类HttpServletBean找到了init方法的入口,进入HttpServletBean的init()方法

public final void init() throws ServletException {
        //去掉了if判断
        // Set bean properties from init parameters.
        PropertyValues pvs = new ServletConfigPropertyValues(getServletConfig(), this.requiredProperties);
        if (!pvs.isEmpty()) {
            try {
                //定位资源
                BeanWrapper bw = PropertyAccessorFactory.forBeanPropertyAccess(this);
                //加载配置信息
                ResourceLoader resourceLoader = new ServletContextResourceLoader(getServletContext());
                bw.registerCustomEditor(Resource.class, new ResourceEditor(resourceLoader, getEnvironment()));
                initBeanWrapper(bw);
                bw.setPropertyValues(pvs, true);
            }
            catch (BeansException ex) {
                if (logger.isErrorEnabled()) {
                    logger.error("Failed to set bean properties on servlet '" + getServletName() + "'", ex);
                }
                throw ex;
            }
        }
        // Let subclasses do whatever initialization they like.
        initServletBean();//Ctrl+Alt+B 选择 FrameworkServlet
        //去掉了if判断
    }

2.initServletBean()上,按住Ctrl+Alt+B,选择FrameworkServlet进入FrameworkServletinitServletBean方法

@Override
    protected final void initServletBean() throws ServletException {
        getServletContext().log("Initializing Spring FrameworkServlet '" + getServletName() + "'");
        //去掉了if判断
        long startTime = System.currentTimeMillis();
        try {
            this.webApplicationContext = initWebApplicationContext();//Ctrl + 鼠标左键
            initFrameworkServlet();
        }
         //去掉了catch块,和下面的if判断
    }

3.initWebApplicationContext() 方法上,按住 Ctrl+鼠标左键进入initWebApplicationContext方法

protected WebApplicationContext initWebApplicationContext() {
        WebApplicationContext rootContext =
                WebApplicationContextUtils.getWebApplicationContext(getServletContext());
        WebApplicationContext wac = null;
​
        if (this.webApplicationContext != null) {
            // A context instance was injected at construction time -> use it
            wac = this.webApplicationContext;
            if (wac instanceof ConfigurableWebApplicationContext) {
                ConfigurableWebApplicationContext cwac = (ConfigurableWebApplicationContext) wac;
                if (!cwac.isActive()) {
                    // The context has not yet been refreshed -> provide services such as
                    // setting the parent context, setting the application context id, etc
                    if (cwac.getParent() == null) {
                        // The context instance was injected without an explicit parent -> set
                        // the root application context (if any; may be null) as the parent
                        cwac.setParent(rootContext);
                    }
                    configureAndRefreshWebApplicationContext(cwac);//支线(会进入SpringIOC的定位阶段)
                }
            }
        }
        if (wac == null) {
            //在构建时没有注入上下文实例——>查看是否有一个已经在servlet上下文中注册。
            //如果存在,则假定已经设置了父上下文(如果有),
            //并且用户已经执行了任何初始化,例如设置上下文id
            wac = findWebApplicationContext();
        }
        if (wac == null) {
            //没有为这个servlet定义上下文实例——>创建一个本地实例
            wac = createWebApplicationContext(rootContext);
        }
​
        if (!this.refreshEventReceived) {
            // Either the context is not a ConfigurableApplicationContext with refresh
            // support or the context injected at construction time had already been
            // refreshed -> trigger initial onRefresh manually here.
            onRefresh(wac); //Ctrl+Alt+B  选择 DispatcherServlet
        }
​
        if (this.publishContext) {
            // Publish the context as a servlet context attribute.
            String attrName = getServletContextAttributeName();
            getServletContext().setAttribute(attrName, wac);
            if (this.logger.isDebugEnabled()) {
                this.logger.debug("Published WebApplicationContext of servlet '" + getServletName() +
                        "' as ServletContext attribute with name [" + attrName + "]");
            }
        }
​
        return wac;
    }

4. 若走configureAndRefreshWebApplicationContext方法,会进入Spring IOC 定位阶段,这里不展开,在onRefresh方法上,按住Ctrl+Alt+B 选择进入DispatcherServletonRefresh方法

    @Override
    protected void onRefresh(ApplicationContext context) {
        initStrategies(context);//Ctrl+鼠标左键
    }

5.initStrategies方法上,按住Ctrl+鼠标左键,进入自身的initStrategies方法,初始化九大策略

    protected void initStrategies(ApplicationContext context) {
        //多文件上传的组件
        initMultipartResolver(context);
        //初始化本地语言环境
        initLocaleResolver(context);
        //初始化模板处理器
        initThemeResolver(context);
        //handlerMapping
        initHandlerMappings(context);
        //初始化参数适配器
        initHandlerAdapters(context);
        //初始化异常拦截器
        initHandlerExceptionResolvers(context);
        //初始化视图预处理器
        initRequestToViewNameTranslator(context);
        //初始化视图转换器
        initViewResolvers(context);
        //初始化Flash管理器
        initFlashMapManager(context);
    }

二、运行(调用)阶段

运行(调用)阶段,核心方法是DispatcherServletdoServlet(),核心逻辑由doDispatch()实现 6. 初始化完成后,进入运行(调用)阶段,进入DispatcherServletdoServlet()

protected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception {
        //去掉了if判断以及request赋值
        try {
            doDispatch(request, response);
        }
        finally {
            if (!WebAsyncUtils.getAsyncManager(request).isConcurrentHandlingStarted()) {
                // Restore the original attribute snapshot, in case of an include.
                if (attributesSnapshot != null) {
                    restoreAttributesAfterInclude(request, attributesSnapshot);
                }
            }
        }
    }

7.doDispatch() 方法上,按住Ctrl+鼠标左键进入自身的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 {
            ModelAndView mv = null;
            Exception dispatchException = null;
​
            try {
                // 1.检查是否是文件上传的请求
                processedRequest = checkMultipart(request);
                multipartRequestParsed = (processedRequest != request);
​
                // Determine handler for the current request.
                // 2.取得处理当前请求的controller,这里也称为hanlder,处理器,
                //   第一个步骤的意义就在这里体现了.这里并不是直接返回controller,
                //   而是返回的HandlerExecutionChain请求处理器链对象,
                //   该对象封装了handler和interceptors.
                mappedHandler = getHandler(processedRequest);
                // 如果handler为空,则返回404
                if (mappedHandler == null) {
                    noHandlerFound(processedRequest, response);
                    return;
                }
​
                // Determine handler adapter for the current request.
                //3. 获取处理request的处理器适配器handler adapter
                HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
​
                // Process last-modified header, if supported by the handler.
                // 处理 last-modified 请求头
                String method = request.getMethod();
                boolean isGet = "GET".equals(method);
                if (isGet || "HEAD".equals(method)) {
                    long lastModified = ha.getLastModified(request, mappedHandler.getHandler());
                    if (logger.isDebugEnabled()) {
                        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;
                }
​
                // Actually invoke the handler.
                // 4.实际的处理器处理请求,返回结果视图对象
                mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
​
                if (asyncManager.isConcurrentHandlingStarted()) {
                    return;
                }
​
                // 结果视图对象的处理
                applyDefaultViewName(processedRequest, mv);
                mappedHandler.applyPostHandle(processedRequest, response, mv);//支线
            }
            catch (Exception ex) {
                dispatchException = ex;
            }
            catch (Throwable err) {
                // As of 4.3, we're processing Errors thrown from handler methods as well,
                // making them available for @ExceptionHandler methods and other scenarios.
                dispatchException = new NestedServletException("Handler dispatch failed", err);
            }
            processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);//主线
        }
        catch (Exception ex) {
            triggerAfterCompletion(processedRequest, response, mappedHandler, ex);
        }
        catch (Throwable err) {
            triggerAfterCompletion(processedRequest, response, mappedHandler,
                    new NestedServletException("Handler processing failed", err));
        }
        finally {
            if (asyncManager.isConcurrentHandlingStarted()) {
                // Instead of postHandle and afterCompletion
                if (mappedHandler != null) {
                    // 请求成功响应之后的方法
                    mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response);
                }
            }
            else {
                // Clean up any resources used by a multipart request.
                if (multipartRequestParsed) {
                    cleanupMultipart(processedRequest);
                }
            }
        }
    }

8.getHandler方法上,按住Ctrl+鼠标左键进入getHandler方法后,返回的是HandlerExecutionChain

    protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
        if (this.handlerMappings != null) {
            for (HandlerMapping hm : this.handlerMappings) {
                if (logger.isTraceEnabled()) {
                    logger.trace(
                            "Testing handler map [" + hm + "] in DispatcherServlet with name '" + getServletName() + "'");
                }
                HandlerExecutionChain handler = hm.getHandler(request);
                if (handler != null) {
                    return handler;
                }
            }
        }
        return null;
    }

9. Ctrl+Alt+键盘左键头返回到第7步,在applyPreHandle方法上,按住Ctrl+Alt+B进入HandlerExecutionChainapplyPreHandle方法

	boolean applyPreHandle(HttpServletRequest request, HttpServletResponse response) throws Exception {
		HandlerInterceptor[] interceptors = getInterceptors();
		if (!ObjectUtils.isEmpty(interceptors)) {
			for (int i = 0; i < interceptors.length; i++) {
				HandlerInterceptor interceptor = interceptors[i];
				if (!interceptor.preHandle(request, response, this.handler)) {
					triggerAfterCompletion(request, response, null);
					return false;
				}
				this.interceptorIndex = i;
			}
		}
		return true;
	}

10.preHandle方法上,按Ctrl+Alt+B进入HandlerInterceptorpreHandle方法,默认返回true。 preHandlehandle前置处理

	default boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
			throws Exception {

		return true;
	}

11. 按住Ctrl+Alt+键盘左键头返回到第7步,在handle方法上,按住Ctrl+Alt+B,进入AbstractHandlerMethodAdapterhandle方法

	public final ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler)
			throws Exception {

		return handleInternal(request, response, (HandlerMethod) handler);
	}

12.handleInternal方法上,按住Ctrl+Alt+B进入RequestMappingHandlerAdapterhandleInternal方法

protected ModelAndView handleInternal(HttpServletRequest request,
			HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {

		ModelAndView mav;
		checkRequest(request);

		// Execute invokeHandlerMethod in synchronized block if required.
		if (this.synchronizeOnSession) {
			HttpSession session = request.getSession(false);
			if (session != null) {
				Object mutex = WebUtils.getSessionMutex(session);
				synchronized (mutex) {
					mav = invokeHandlerMethod(request, response, handlerMethod);
				}
			}
			else {
				// No HttpSession available -> no mutex necessary
				mav = invokeHandlerMethod(request, response, handlerMethod);
			}
		}
		else {
			// No synchronization on session demanded at all...
			mav = invokeHandlerMethod(request, response, handlerMethod);
		}

		if (!response.containsHeader(HEADER_CACHE_CONTROL)) {
			if (getSessionAttributesHandler(handlerMethod).hasSessionAttributes()) {
				applyCacheSeconds(response, this.cacheSecondsForSessionAttributeHandlers);
			}
			else {
				prepareResponse(response);
			}
		}

		return mav;
	}

13.invokeHandlerMethod方法上,按住Ctrl+鼠标左键进入自身的invokeHandlerMethod方法

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

	//去掉了if判断和finally
	return getModelAndView(mavContainer, modelFactory, webRequest); 
}

14.getModelAndView方法上,按住Ctrl+鼠标左键进入自身的getModelAndView方法,返回ModelAndView

	private ModelAndView getModelAndView(ModelAndViewContainer mavContainer,
			ModelFactory modelFactory, NativeWebRequest webRequest) throws Exception {

		modelFactory.updateModel(webRequest, mavContainer);
		if (mavContainer.isRequestHandled()) {
			return null;
		}
		ModelMap model = mavContainer.getModel();
		ModelAndView mav = new ModelAndView(mavContainer.getViewName(), model, mavContainer.getStatus());
		if (!mavContainer.isViewReference()) {
			mav.setView((View) mavContainer.getView());
		}
		if (model instanceof RedirectAttributes) {
			Map<String, ?> flashAttributes = ((RedirectAttributes) model).getFlashAttributes();
			HttpServletRequest request = webRequest.getNativeRequest(HttpServletRequest.class);
			if (request != null) {
				RequestContextUtils.getOutputFlashMap(request).putAll(flashAttributes);
			}
		}
		return mav;
	}

15. 按住Ctrl+Alt+键盘左键头返回到第7步,在applyPostHandle方法上,按住Ctrl+鼠标左键,进入HandlerExecutionChainapplyPostHandle方法

	void applyPostHandle(HttpServletRequest request, HttpServletResponse response, @Nullable ModelAndView mv)
			throws Exception {

		HandlerInterceptor[] interceptors = getInterceptors();
		if (!ObjectUtils.isEmpty(interceptors)) {
			for (int i = interceptors.length - 1; i >= 0; i--) {
				HandlerInterceptor interceptor = interceptors[i];
				interceptor.postHandle(request, response, this.handler, mv);
			}
		}
	}

16.postHandle方法上,按住Ctrl+Alt+B,选择HandlerInterceptor,进入到HandlerInterceptorpostHandle方法,postHandle方法为handle的后置方法

	default void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
			@Nullable ModelAndView modelAndView) throws Exception {
	}

17. 按住Ctrl+Alt+键盘左键头返回到第7步,在processDispatchResult方法上,按住Ctrl+鼠标左键进入processDispatchResult方法

private void processDispatchResult(HttpServletRequest request, HttpServletResponse response,
									   @Nullable HandlerExecutionChain mappedHandler, @Nullable ModelAndView mv,
									   @Nullable Exception exception) throws Exception {

		boolean errorView = false;

		if (exception != null) {
			if (exception instanceof ModelAndViewDefiningException) {
				logger.debug("ModelAndViewDefiningException encountered", exception);
				mv = ((ModelAndViewDefiningException) exception).getModelAndView();
			}
			else {
				Object handler = (mappedHandler != null ? mappedHandler.getHandler() : null);
				mv = processHandlerException(request, response, handler, exception);
				errorView = (mv != null);
			}
		}

		// Did the handler return a view to render?
		if (mv != null && !mv.wasCleared()) {
			render(mv, request, response);//Ctrl+鼠标左键
			if (errorView) {
				WebUtils.clearErrorRequestAttributes(request);
			}
		}
		else {
			if (logger.isDebugEnabled()) {
				logger.debug("Null ModelAndView returned to DispatcherServlet with name '" + getServletName() +
						"': assuming HandlerAdapter completed request handling");
			}
		}

		if (WebAsyncUtils.getAsyncManager(request).isConcurrentHandlingStarted()) {
			// Concurrent handling started during a forward
			return;
		}

		if (mappedHandler != null) {
			mappedHandler.triggerAfterCompletion(request, response, null);
		}
	}

18.render方法上,按住Ctrl+鼠标左键进入自身的render方法

protected void render(ModelAndView mv, HttpServletRequest request, HttpServletResponse response) throws Exception {
		// Determine locale for request and apply it to the response.
		Locale locale =
				(this.localeResolver != null ? this.localeResolver.resolveLocale(request) : request.getLocale());
		response.setLocale(locale);

		View view;
		String viewName = mv.getViewName();
		if (viewName != null) {
			// We need to resolve the view name.
			view = resolveViewName(viewName, mv.getModelInternal(), locale, request);
			if (view == null) {
				throw new ServletException("Could not resolve view with name '" + mv.getViewName() +
						"' in servlet with name '" + getServletName() + "'");
			}
		}
		else {
			// No need to lookup: the ModelAndView object contains the actual View object.
			view = mv.getView();
			if (view == null) {
				throw new ServletException("ModelAndView [" + mv + "] neither contains a view name nor a " +
						"View object in servlet with name '" + getServletName() + "'");
			}
		}

		// Delegate to the View object for rendering.
		if (logger.isDebugEnabled()) {
			logger.debug("Rendering view [" + view + "] in DispatcherServlet with name '" + getServletName() + "'");
		}
		try {
			if (mv.getStatus() != null) {
				response.setStatus(mv.getStatus().value());
			}
			view.render(mv.getModelInternal(), request, response);//
		}
		catch (Exception ex) {
			if (logger.isDebugEnabled()) {
				logger.debug("Error rendering view [" + view + "] in DispatcherServlet with name '" +
						getServletName() + "'", ex);
			}
			throw ex;
		}
	}

19.render方法上,按住Ctrl+Alt+B,选择的AbstractView,进入AbstractViewrender方法,完成运行(调用)阶段。

	public void render(@Nullable Map<String, ?> model, HttpServletRequest request,
			HttpServletResponse response) throws Exception {

		if (logger.isTraceEnabled()) {
			logger.trace("Rendering view with name '" + this.beanName + "' with model " + model +
				" and static attributes " + this.staticAttributes);
		}

		Map<String, Object> mergedModel = createMergedOutputModel(model, request, response);
		prepareResponse(request, response);
		renderMergedOutputModel(mergedModel, getRequestToExpose(request), response);
	}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值