Spring MVC 运行流程源码剖析

一、Spring MVC请求处理流程

在这里插入图片描述
流程说明

  • 第一步:用户发送请求至前端控制器DispatcherServlet
  • 第二步:DispatcherServlet收到请求调用HandlerMapping处理器映射器
  • 第三步:处理器映射器根据请求Url找到具体的Handler(早期指实现Controller接口的类,现在注解模式下,类中的每个方法都是一个Handler),生成处理器对象及处理器拦截器(如果有则生成)⼀并返回DispatcherServlet
  • 第四步:DispatcherServlet调用HandlerAdapter处理器适配器去调用Handler
  • 第五步:处理器适配器执行Handler
  • 第六步:Handler执行完成给处理器适配器返回ModelAndView
  • 第七步:处理器适配器向前端控制器返回 ModelAndView,ModelAndView 是SpringMVC 框架的⼀个底层对象,包括 Model 和 View
  • 第八步:前端控制器请求视图解析器去进行视图解析,根据逻辑视图名来解析真正的视图。
  • 第九步:视图解析器向前端控制器返回View
  • 第十步:前端控制器进行视图渲染,就是将模型数据(在 ModelAndView 对象中)填充到 request 域
  • 第十一步:前端控制器向用户响应结果

二、前端控制器DispatcherServlet继承体系

在这里插入图片描述
  流程分析:前端发送一个请求,进入到Servlet的service方法,再进入到 FrameworkServlet 的doGet()/doPost(),该方法调用processRequest() 方法处理请求,在该方法里面调用DispatcherServlet 的 doService() 方法,doService() 调用 doDispatch() 方法,该方法是整个Spring MVC处理请求的核心方法。
源码

public class DispatcherServlet extends FrameworkServlet{
	......
}
public abstract class FrameworkServlet extends HttpServletBean implements ApplicationContextAware {
	......
}
public abstract class HttpServletBean extends HttpServlet implements EnvironmentCapable, EnvironmentAware {
	......
}

  通过源码可看到:DispatcherServlet是继承FrameworkServlet,FrameworkServlet继承HttpServletBean,这三个Servlet都是是Spring MVC提供的类,HttpServlet继承HttpServlet,该类是一个Servlet类,它有一个最终的方法,就是service()方法,它是Serlet最核心的方法。

三、Handler调用栈

  接下来我们看一下一个Handler的调用栈是怎么样的。
在这里插入图片描述
  从调用栈中我们可以看出,一个请求过来,先进入FrameworkServlet的 service() 方法,在进入 doGet() 方法,在进入 processRequest() 方法,在进入 DispatcherServlet 的 doService() 方法,在进入doDispatch(),在该方法的1064行代码执行了Handler方法。

FrameworkServlet

	/**
	 * Delegate GET requests to processRequest/doService.
	 * <p>Will also be invoked by HttpServlet's default implementation of {@code doHead},
	 * with a {@code NoBodyResponse} that just captures the content length.
	 * @see #doService
	 * @see #doHead
	 */
	@Override
	protected final void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {

		processRequest(request, response);
	}

	/**
	 * Delegate POST requests to {@link #processRequest}.
	 * @see #doService
	 */
	@Override
	protected final void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {

		processRequest(request, response);
	}

  FrameworkServlet的 doGet() 和 doPost() 方法都是调用了 processRequest() 方法

	/**
	 * Process this request, publishing an event regardless of the outcome.
	 * <p>The actual event handling is performed by the abstract
	 * {@link #doService} template method.
	 */
	protected final void processRequest(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {

		long startTime = System.currentTimeMillis();
		Throwable failureCause = null;

		// 获取上一个请求保存的LocaleContext
		LocaleContext previousLocaleContext = LocaleContextHolder.getLocaleContext();
		// 建立新的LocaleContext
		LocaleContext localeContext = buildLocaleContext(request);

		// 获取上一个请求保存的RequestAttributes
		RequestAttributes previousAttributes = RequestContextHolder.getRequestAttributes();
		// 建立新的RequestAttributes
		ServletRequestAttributes requestAttributes = buildRequestAttributes(request, response, previousAttributes);

		WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
		asyncManager.registerCallableInterceptor(FrameworkServlet.class.getName(), new RequestBindingInterceptor());

		// 新的RequestAttributes设置进LocalThread
		initContextHolders(request, localeContext, requestAttributes);

		try {
			doService(request, response);
		}
		catch (ServletException | IOException ex) {
			failureCause = ex;
			throw ex;
		}
		catch (Throwable ex) {
			failureCause = ex;
			throw new NestedServletException("Request processing failed", ex);
		}

		finally {
			resetContextHolders(request, previousLocaleContext, previousAttributes);
			if (requestAttributes != null) {
				requestAttributes.requestCompleted();
			}
			logResult(request, response, failureCause, asyncManager);
			publishRequestHandledEvent(request, response, startTime, failureCause);
		}
	}

  processRequest()最终调用 doService() 方法,而该方法在 FrameworkServlet 中是一个抽象方法,具体实现是在子类 DispatcherServlet 中

	protected abstract void doService(HttpServletRequest request, HttpServletResponse response)
			throws Exception;

DispatcherServlet

	/**
	 * Exposes the DispatcherServlet-specific request attributes and delegates to {@link #doDispatch}
	 * for the actual dispatching.
	 */
	@Override
	protected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception {
		logRequest(request);

		// Keep a snapshot of the request attributes in case of an include,
		// to be able to restore the original attributes after the include.
		Map<String, Object> attributesSnapshot = null;
		if (WebUtils.isIncludeRequest(request)) {
			attributesSnapshot = new HashMap<>();
			Enumeration<?> attrNames = request.getAttributeNames();
			while (attrNames.hasMoreElements()) {
				String attrName = (String) attrNames.nextElement();
				if (this.cleanupAfterInclude || attrName.startsWith(DEFAULT_STRATEGIES_PREFIX)) {
					attributesSnapshot.put(attrName, request.getAttribute(attrName));
				}
			}
		}

		// Make framework objects available to handlers and view objects.
		request.setAttribute(WEB_APPLICATION_CONTEXT_ATTRIBUTE, getWebApplicationContext());
		request.setAttribute(LOCALE_RESOLVER_ATTRIBUTE, this.localeResolver);
		request.setAttribute(THEME_RESOLVER_ATTRIBUTE, this.themeResolver);
		request.setAttribute(THEME_SOURCE_ATTRIBUTE, getThemeSource());

		if (this.flashMapManager != null) {
			FlashMap inputFlashMap = this.flashMapManager.retrieveAndUpdate(request, response);
			if (inputFlashMap != null) {
				request.setAttribute(INPUT_FLASH_MAP_ATTRIBUTE, Collections.unmodifiableMap(inputFlashMap));
			}
			request.setAttribute(OUTPUT_FLASH_MAP_ATTRIBUTE, new FlashMap());
			request.setAttribute(FLASH_MAP_MANAGER_ATTRIBUTE, this.flashMapManager);
		}

		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);
				}
			}
		}
	}

  DispatcherServlet中的 doService() 方法最终调用 doDispatch() 方法,该方法是Spring MVC处理请求的核心方法,整个源码分析主要就是分析该方法。

	/**
	 * Process the actual dispatching to the handler.
	 * <p>The handler will be obtained by applying the servlet's HandlerMappings in order.
	 * The HandlerAdapter will be obtained by querying the servlet's installed HandlerAdapters
	 * to find the first that supports the handler class.
	 * <p>All HTTP methods are handled by this method. It's up to HandlerAdapters or handlers
	 * themselves to decide which methods are acceptable.
	 * @param request current HTTP request
	 * @param response current HTTP response
	 * @throws Exception in case of any kind of processing failure
	 */
	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,这里也称为Handler,即处理器
				 	  这里并不是直接返回 Controller,而是返回 HandlerExecutionChain 请求处理链对象
				 	  该对象封装了Handler和Inteceptor
				 */
				mappedHandler = getHandler(processedRequest);
				if (mappedHandler == null) {
					// 如果 handler 为空,则返回404
					noHandlerFound(processedRequest, response);
					return;
				}

				// Determine handler adapter for the current request.
				// 3 获取处理请求的处理器适配器 HandlerAdapter
				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 (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);
			}
			// 5 处理请求结果(视图渲染和页面转发)
			processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
		}
		catch (Exception ex) {
			//最终会调用HandlerInterceptor的afterCompletion 方法
			triggerAfterCompletion(processedRequest, response, mappedHandler, ex);
		}
		catch (Throwable err) {
			//最终会调用HandlerInterceptor的afterCompletion 方法
			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);
				}
			}
		}
	}

  Spring MVC处理请求的流程即为 DispatcherServlet 中 doDispatch() 方法法的执⾏过程,其中步骤2、3、4、5是核心步骤

  1. 调用 getHandler() 获取到能够处理当前请求的执行链 HandlerExecutionChain(Handler + 拦截器)
    但是如何去getHandler的?后面进行发恩熙
  2. 调用 getHandlerAdapter():获取能够执行 1 中Handler的适配器
    但是如何去getHandlerAdapter的?后面进行分析
  3. 适配器调用 Handler 执行 ha.handle(最终返回⼀个ModelAndView对象)
  4. 调用processDispatchResult()方法完成视图渲染跳转

四、doDispatch()方法

4.1、核心步骤getHandler()方法剖析

  首先我们先看一下HandlerMapping 的继承体系
在这里插入图片描述
  从图中我们可以看到AbstractHandlerMapping有两个分支,一个是AbstractHandlerMethodMapping,一个是AbstractUrlHandlerMapping。

  • AbstractHandlerMethodMapping 这个分支获取的 Handler 的类型是HandlerMethod,即这个 Handler 是一个方法,它保存了方法的信息(如Method),这样一个Controller就可以处理多个请求了。
  • AbstractUrlHandlerMapping 这个分支获取的 Handler 的类型实际就是一个 Controller 类,所以一个 Controller 只能对应一个请求。早期一个类实现Controller接口就把这个类当做一个Handler。

首先先了解一下两个问题:
1、Handler是什么?
  Handler 有可能是一个 HandlerMethod(封装了 Controller 中的方法)对象,也有可能是一个 Controller 对象、 HttpRequestHandler 对象或 Servlet 对象,而这个 Handler 具体是什么对象,也是与所使用的 HandlerMapping 实现类有关。

2、为什么要去找HandlerMapping获取一个Handler呢?
  Handler对象有两种实现方式,一种是通过实现Controller接口,某个实现Controller接口的话,该类就是一个Handler。一种是实现@RequestMapping注解,那么使用该注解标注的一个方法就是一个Handler。所以需要不同的HandlerMapping去解析不同的Handler。

进入正题
  getHandler() 方法的作用就是根据当前的请求去获取处理当前请求的Handler(Controller中的一个方法),即处理器。这里并不是直接返回Handler,而是返回 HandlerExecutionChain 请求处理链对象,该对象封装了 Handler + Inteceptor拦截器链。

DispatcherServlet

	/**
	 * Return the HandlerExecutionChain for this request.
	 * <p>Tries all handler mappings in order.
	 * @param request current HTTP request
	 * @return the HandlerExecutionChain, or {@code null} if no handler could be found
	 */
	@Nullable
	protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
		if (this.handlerMappings != null) {
			for (HandlerMapping mapping : this.handlerMappings) {
				HandlerExecutionChain handler = mapping.getHandler(request);
				if (handler != null) {
					return handler;
				}
			}
		}
		return null;
	}	

  断点看一下 getHandler() 的调用,如下图可以看出getHandler()方法就是遍历handlerMappings,然后调用HandMapping的getHandler(request) 方法。handlerMappings在容器初始化后又两个,分别是BeanNameUrlHandlerMapping 和 RequestMappingHandlerMapping,那么问题来了,handlerMappings是什么时候初始化的呢?后面再分析。
在这里插入图片描述

4.2、核心步骤 getHandlerAdapter() 方法剖析

  首先我们看一下HandlerAdapter的继承体系
在这里插入图片描述
  从上面的文章中可以知道,利用 RequestMappingHandlerMapping 获取的 Handler 是 HadnlerMethod 类型,它代表 Controller 里要执行的方法,而 RequestMappingHandlerAdapter 可以执行 HadnlerMethod 对象。RequestMappingHandlerAdapter 的 handle() 方法是在它的父类 AbstractHandlerMethodAdapter 类中实现的,

进入正题:
  getHandlerAdapter()方法的作用就是获取能够处理该请求的HandlerAdapter(处理器适配器)

	/**
	 * Return the HandlerAdapter for this handler object.
	 * @param handler the handler object to find an adapter for
	 * @throws ServletException if no HandlerAdapter can be found for the handler. This is a fatal error.
	 */
	protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException {
		if (this.handlerAdapters != null) {
			for (HandlerAdapter adapter : this.handlerAdapters) {
				if (adapter.supports(handler)) {
					return adapter;
				}
			}
		}
		throw new ServletException("No adapter for handler [" + handler +
				"]: The DispatcherServlet configuration needs to include a HandlerAdapter that supports this handler");
	}

  断点看一下 getHandlerAdapter() 的调用,如下图可以看出 getHandlerAdapter() 方法就是遍历handlerAdapters,然后调用HandlerAdapter的supports(handler) 方法判断是否是能够处理当前Handler的适配器。handlerAdapters在容器初始化后有3个,分别是 HttpRequestHandlerAdapter、SimpleControllerHandlerAdapter 和 RequestMappingHandlerAdapter,那么问题来了,handlerAdapters是什么时候初始化的呢?和handlerMappings一样,我们放后面再分析。
在这里插入图片描述
  分别看下这3个HandlerAdapter 中supports方法是怎么实现的

HttpRequestHandlerAdapter:判断该Handler是否实现 HttpRequestHandler 接口

public class HttpRequestHandlerAdapter implements HandlerAdapter {

	@Override
	public boolean supports(Object handler) {
		return (handler instanceof HttpRequestHandler);
	}
}

SimpleControllerHandlerAdapter:判断该Handler是否实现 Controller 接口

public class SimpleControllerHandlerAdapter implements HandlerAdapter {

	@Override
	public boolean supports(Object handler) {
		return (handler instanceof Controller);
	}
	
}

RequestMappingHandlerAdapter,该类中无supports方法,在父类AbstractHandlerMethodAdapter中实现

AbstractHandlerMethodAdapter:判断该Handler是否继承 HandlerMethod

public abstract class AbstractHandlerMethodAdapter extends WebContentGenerator implements HandlerAdapter, Ordered {
	
	@Override
	public final boolean supports(Object handler) {
		return (handler instanceof HandlerMethod && supportsInternal((HandlerMethod) handler));
	}
	
}

4.3、核心步骤ha.handler方法剖析

  该方法是处理器适配器处理请求,返回结果视图对象
在这里插入图片描述
  从图中可以看出,此次我们使用到的处理器适配器是RequestMappingHandlerAdapter,即 ha.handler() 实际调用的是 RequestMappingHandlerAdapter 中的 handler() 方法,查看RequestMappingHandlerAdapter源码可以看到该类并没有handler() 方法,所以往上看一下父类AbstractHandlerMethodAdapter,在父类中找到了 handler 方法,所以此处实际调用的是 AbstractHandlerMethodAdapter 中 handler 方法。

AbstractHandlerMethodAdapter

	/**
	 * This implementation expects the handler to be an {@link HandlerMethod}.
	 */
	@Override
	@Nullable
	public final ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler)
			throws Exception {

		return handleInternal(request, response, (HandlerMethod) handler);
	}
	
	@Nullable
	protected abstract ModelAndView handleInternal(HttpServletRequest request,
			HttpServletResponse response, HandlerMethod handlerMethod) throws Exception;

  父类中 handler 方法最终调用的是 handleInternal 方法,而该方法是一个抽象方法,具体实现是在子类RequestMappingHandlerAdapter 中。

RequestMappingHandlerAdapter

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

		ModelAndView mav;
		checkRequest(request);

		// Execute invokeHandlerMethod in synchronized block if required.
		// 判断当前是否需要支持在同一个session中只能线性地处理请求
		if (this.synchronizeOnSession) {
			// 获取当前请求的session对象
			HttpSession session = request.getSession(false);
			if (session != null) {
				// 为当前session生成一个唯一的可以用于锁定的key
				Object mutex = WebUtils.getSessionMutex(session);
				synchronized (mutex) {
					// 对HandlerMethod进行参数等的适配处理,并调用目标handler
					mav = invokeHandlerMethod(request, response, handlerMethod);
				}
			}
			else {
				// No HttpSession available -> no mutex necessary
				// 如果当前不存在session,则直接对HandlerMethod进行适配
				mav = invokeHandlerMethod(request, response, handlerMethod);
			}
		}
		else {
			// No synchronization on session demanded at all...
			// 如果当前不需要对session进行同步处理,则直接对HandlerMethod进行适配
			mav = invokeHandlerMethod(request, response, handlerMethod);
		}

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

		return mav;
	}

  handleInternal 调用 invokeHandlerMethod

	/**
	 * Invoke the {@link RequestMapping} handler method preparing a {@link ModelAndView}
	 * if view resolution is required.
	 * @since 4.2
	 * @see #createInvocableHandlerMethod(HandlerMethod)
	 */
	@Nullable
	protected ModelAndView invokeHandlerMethod(HttpServletRequest request,
			HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {

		ServletWebRequest webRequest = new ServletWebRequest(request, response);
		try {
			// 获取容器中全局配置的InitBinder和当前HandlerMethod所对应的Controller中配置的InitBinder,用于进行参数的绑定
			WebDataBinderFactory binderFactory = getDataBinderFactory(handlerMethod);
			// 获取容器中全局配置的ModelAttribute和当前当前HandlerMethod所对应的Controller中配置的ModelAttribute,这些配置的方法将会在目标方法调用之前进行调用
			ModelFactory modelFactory = getModelFactory(handlerMethod, binderFactory);

			// 将handlerMethod封装为一个ServletInvocableHandlerMethod对象
			ServletInvocableHandlerMethod invocableMethod = createInvocableHandlerMethod(handlerMethod);
			if (this.argumentResolvers != null) {
				// 设置当前容器中配置的所有ArgumentResolver
				invocableMethod.setHandlerMethodArgumentResolvers(this.argumentResolvers);
			}
			if (this.returnValueHandlers != null) {
				// 设置当前容器中配置的所有ReturnValueHandler
				invocableMethod.setHandlerMethodReturnValueHandlers(this.returnValueHandlers);
			}
			// 将前面创建的WebDataBinderFactory设置到ServletInvocableHandlerMethod中
			invocableMethod.setDataBinderFactory(binderFactory);

			invocableMethod.setParameterNameDiscoverer(this.parameterNameDiscoverer);

			ModelAndViewContainer mavContainer = new ModelAndViewContainer();
			mavContainer.addAllAttributes(RequestContextUtils.getInputFlashMap(request));
			// 这里initModel()方法主要作用是调用前面获取到的@ModelAttribute标注的方法,
			// 从而达到@ModelAttribute标注的方法能够在目标Handler调用之前调用的目的
			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()) {
				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);
			}

			// 对请求参数进行处理,调用目标HandlerMethod,并且将返回值封装为一个ModelAndView对象
			invocableMethod.invokeAndHandle(webRequest, mavContainer);
			if (asyncManager.isConcurrentHandlingStarted()) {
				return null;
			}

			// 对封装的ModelAndView进行处理,主要是判断当前请求是否进行了重定向,如果进行了重定向,
			// 还会判断是否需要将FlashAttributes封装到新的请求中
			return getModelAndView(mavContainer, modelFactory, webRequest);
		}
		finally {
			webRequest.requestCompleted();
		}
	}

  该方法先将handlerMethod封装为一个ServletInvocableHandlerMethod对象,在调用该对象的 invokeAndHandle 方法

ServletInvocableHandlerMethod

	/**
	 * Invoke the method and handle the return value through one of the
	 * configured {@link HandlerMethodReturnValueHandler HandlerMethodReturnValueHandlers}.
	 * @param webRequest the current request
	 * @param mavContainer the ModelAndViewContainer for this request
	 * @param providedArgs "given" arguments matched by type (not resolved)
	 */
	public void invokeAndHandle(ServletWebRequest webRequest, ModelAndViewContainer mavContainer,
			Object... providedArgs) throws Exception {

		// 对目标handler的参数进行处理,并且调用目标handler
		Object returnValue = invokeForRequest(webRequest, mavContainer, providedArgs);
		// 设置相关的返回状态
		setResponseStatus(webRequest);

		if (returnValue == null) {
			if (isRequestNotModified(webRequest) || getResponseStatus() != null || mavContainer.isRequestHandled()) {
				disableContentCachingIfNecessary(webRequest);
				mavContainer.setRequestHandled(true);
				return;
			}
		}
		else if (StringUtils.hasText(getResponseStatusReason())) {
			mavContainer.setRequestHandled(true);
			return;
		}

		mavContainer.setRequestHandled(false);
		Assert.state(this.returnValueHandlers != null, "No return value handlers");
		try {
			this.returnValueHandlers.handleReturnValue(
					returnValue, getReturnValueType(returnValue), mavContainer, webRequest);
		}
		catch (Exception ex) {
			if (logger.isTraceEnabled()) {
				logger.trace(formatErrorForReturnValue(returnValue), ex);
			}
			throw ex;
		}
	}

  该方法调用父类InvocableHandlerMethod 的 invokeForRequest 方法完成 handler 的调用。

InvocableHandlerMethod

	@Nullable
	public Object invokeForRequest(NativeWebRequest request, @Nullable ModelAndViewContainer mavContainer,
			Object... providedArgs) throws Exception {

		//  将request中的参数转换为当前handler的参数形式
		Object[] args = getMethodArgumentValues(request, mavContainer, providedArgs);
		if (logger.isTraceEnabled()) {
			logger.trace("Arguments: " + Arrays.toString(args));
		}
		// 这里doInvoke()方法主要是结合处理后的参数,使用反射对目标方法进行调用
		return doInvoke(args);
	}

将request中的参数转换为当前handler的参数形式

	/**
	 * Get the method argument values for the current request, checking the provided
	 * argument values and falling back to the configured argument resolvers.
	 * <p>The resulting array will be passed into {@link #doInvoke}.
	 * @since 5.1.2
	 * 本方法主要是通过当前容器中配置的ArgumentResolver对request中的参数进行转化,
	 * 将其处理为目标handler的参数的形式
	 */
	protected Object[] getMethodArgumentValues(NativeWebRequest request, @Nullable ModelAndViewContainer mavContainer,
			Object... providedArgs) throws Exception {

		// 获取当前handler所声明的所有参数,主要包括参数名,参数类型,参数位置,所标注的注解等等属性
		MethodParameter[] parameters = getMethodParameters();
		if (ObjectUtils.isEmpty(parameters)) {
			return EMPTY_ARGS;
		}

		Object[] args = new Object[parameters.length];
		for (int i = 0; i < parameters.length; i++) {
			MethodParameter parameter = parameters[i];
			parameter.initParameterNameDiscovery(this.parameterNameDiscoverer);
			// providedArgs是调用方提供的参数,这里主要是判断这些参数中是否有当前类型,如果有,则直接使用调用方提供的参数,对于请求处理而言,默认情况下,
			// 调用方提供的参数都是长度为0的数组
			args[i] = findProvidedArgument(parameter, providedArgs);
			if (args[i] != null) {
				continue;
			}
			// 如果在调用方提供的参数中不能找到当前类型的参数值,则遍历Spring容器中所有的
			// ArgumentResolver,判断哪种类型的Resolver支持对当前参数的解析,这里的判断
			// 方式比较简单,比如RequestParamMethodArgumentResolver就是判断当前参数
			// 是否使用@RequestParam注解进行了标注
			if (!this.resolvers.supportsParameter(parameter)) {
				throw new IllegalStateException(formatArgumentError(parameter, "No suitable resolver"));
			}
			try {
				// 如果能够找到对当前参数进行处理的ArgumentResolver,则调用其
				// resolveArgument()方法从request中获取对应的参数值,并且进行转换
				args[i] = this.resolvers.resolveArgument(parameter, mavContainer, request, this.dataBinderFactory);
			}
			catch (Exception ex) {
				// Leave stack trace for later, exception may actually be resolved and handled...
				if (logger.isDebugEnabled()) {
					String exMsg = ex.getMessage();
					if (exMsg != null && !exMsg.contains(parameter.getExecutable().toGenericString())) {
						logger.debug(formatArgumentError(parameter, exMsg));
					}
				}
				throw ex;
			}
		}
		return args;
	}

  doInvoke()方法主要是结合处理后的参数,使用反射对目标方法进行调用

	@Nullable
	protected Object doInvoke(Object... args) throws Exception {
		ReflectionUtils.makeAccessible(getBridgedMethod());
		try {
			// 使用反射执行目标对象的方法
			return getBridgedMethod().invoke(getBean(), args);
		}
		catch (IllegalArgumentException ex) {
			assertTargetBean(getBridgedMethod(), getBean(), args);
			String text = (ex.getMessage() != null ? ex.getMessage() : "Illegal argument");
			throw new IllegalStateException(formatInvokeError(text, args), ex);
		}
		catch (InvocationTargetException ex) {
			// Unwrap for HandlerExceptionResolvers ...
			Throwable targetException = ex.getTargetException();
			if (targetException instanceof RuntimeException) {
				throw (RuntimeException) targetException;
			}
			else if (targetException instanceof Error) {
				throw (Error) targetException;
			}
			else if (targetException instanceof Exception) {
				throw (Exception) targetException;
			}
			else {
				throw new IllegalStateException(formatInvokeError("Invocation failure", args), targetException);
			}
		}
	}

4.4、核心步骤processDispatchResult方法剖析

	/**
	 * Handle the result of handler selection and handler invocation, which is
	 * either a ModelAndView or an Exception to be resolved to a ModelAndView.
	 */
	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);
			if (errorView) {
				WebUtils.clearErrorRequestAttributes(request);
			}
		}
		else {
			if (logger.isTraceEnabled()) {
				logger.trace("No view rendering, null ModelAndView returned.");
			}
		}

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

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

  主要是执行render方法完成渲染

	/**
	 * Render the given ModelAndView.
	 * <p>This is the last stage in handling a request. It may involve resolving the view by name.
	 * @param mv the ModelAndView to render
	 * @param request current HTTP servlet request
	 * @param response current HTTP servlet response
	 * @throws ServletException if view is missing or cannot be resolved
	 * @throws Exception if there's a problem rendering the view
	 */
	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对象
			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.isTraceEnabled()) {
			logger.trace("Rendering view [" + view + "] ");
		}
		try {
			if (mv.getStatus() != null) {
				response.setStatus(mv.getStatus().value());
			}
			// 调⽤了view对象的render⽅法渲染数据
			view.render(mv.getModelInternal(), request, response);
		}
		catch (Exception ex) {
			if (logger.isDebugEnabled()) {
				logger.debug("Error rendering view [" + view + "]", ex);
			}
			throw ex;
		}
	}

render方法主要有两个大的步骤:

(1)通过视图解析器解析获取视图对象View
(2)调用view.render()将model中的数据填充到请求域中。

4.4.1 通过视图解析器解析获取视图对象View

  先看一下视图解析器 InternalResourceViewResolver 的继承体系
在这里插入图片描述
  调用视图解析器解析视图名,获取View对象。此处viewResolver是InternalResourceViewResolver视图解析器。InternalResourceViewResolver 和 UrlBasedViewResolver 中无 resolveViewName() 方法,所以 viewResolver.resolveViewName(viewName, locale) 调用的是父类 AbstractCachingViewResolver 中的 resolveViewName() 方法。

	@Nullable
	protected View resolveViewName(String viewName, @Nullable Map<String, Object> model,
			Locale locale, HttpServletRequest request) throws Exception {

		if (this.viewResolvers != null) {
			for (ViewResolver viewResolver : this.viewResolvers) {
				View view = viewResolver.resolveViewName(viewName, locale);
				if (view != null) {
					return view;
				}
			}
		}
		return null;
	}		

AbstractCachingViewResolver

`@Override
	@Nullable
	public View resolveViewName(String viewName, Locale locale) throws Exception {
		// // 是否启用缓存,可通过setCache()方法或setCacheLimit()方法开启缓存,是一个ConcurrentHashMap,默认缓存大小1024
		if (!isCache()) {
			return createView(viewName, locale);
		}
		else {
			// 得到 view 在缓存中的 key 值
			Object cacheKey = getCacheKey(viewName, locale);
			View view = this.viewAccessCache.get(cacheKey);
			// 如果没有找到 view 则创建,采用双重校验的方式进行安全创建
			if (view == null) {
				synchronized (this.viewCreationCache) {
					view = this.viewCreationCache.get(cacheKey);
					if (view == null) {
						// Ask the subclass to create the View object.
						// 具体的创建方式由子类实现
						view = createView(viewName, locale);
						if (view == null && this.cacheUnresolved) {
							view = UNRESOLVED_VIEW;
						}
						if (view != null) {
							this.viewAccessCache.put(cacheKey, view);
							this.viewCreationCache.put(cacheKey, view);
						}
					}
				}
			}
			else {
				if (logger.isTraceEnabled()) {
					logger.trace(formatKey(cacheKey) + "served from cache");
				}
			}
			return (view != UNRESOLVED_VIEW ? view : null);
		}
	}

	@Nullable
	protected View createView(String viewName, Locale locale) throws Exception {
		return loadView(viewName, locale);
	}

	@Nullable
	protected abstract View loadView(String viewName, Locale locale) throws Exception;

  从源码中可以看出,最终调用的是 loadView 方法创建View对象,而父类中该方法是抽象方法,具体由子类 UrlBasedViewResolver 中提供实现。

UrlBasedViewResolver

	@Override
	protected View loadView(String viewName, Locale locale) throws Exception {
		AbstractUrlBasedView view = buildView(viewName);
		View result = applyLifecycleMethods(viewName, view);
		return (view.checkResource(locale) ? result : null);
	}

	protected AbstractUrlBasedView buildView(String viewName) throws Exception {
		Class<?> viewClass = getViewClass();
		Assert.state(viewClass != null, "No view class");

		AbstractUrlBasedView view = (AbstractUrlBasedView) BeanUtils.instantiateClass(viewClass);

		// 逻辑视图名转换为物理视图名
		view.setUrl(getPrefix() + viewName + getSuffix());

		String contentType = getContentType();
		if (contentType != null) {
			view.setContentType(contentType);
		}

		view.setRequestContextAttribute(getRequestContextAttribute());
		view.setAttributesMap(getAttributesMap());

		Boolean exposePathVariables = getExposePathVariables();
		if (exposePathVariables != null) {
			view.setExposePathVariables(exposePathVariables);
		}
		Boolean exposeContextBeansAsAttributes = getExposeContextBeansAsAttributes();
		if (exposeContextBeansAsAttributes != null) {
			view.setExposeContextBeansAsAttributes(exposeContextBeansAsAttributes);
		}
		String[] exposedContextBeanNames = getExposedContextBeanNames();
		if (exposedContextBeanNames != null) {
			view.setExposedContextBeanNames(exposedContextBeanNames);
		}

		return view;
	}

4.4.2 视图渲染和页面跳转

  在视图解析器解析完成View对象的创建后,执行View对象的render完成视图渲染和页面跳转
在这里插入图片描述
  从图中我们可以看出此时这个view对象时一个 InternalResourceView,我们先看一下 InternalResourceView 的继承体系。InternalResourceView 和 AbstractUrlBasedView 中并没有 render 方法,所以调用的是AbstractView中的 render 方法。
在这里插入图片描述
AbstractView

	/**
	 * Prepares the view given the specified model, merging it with static
	 * attributes and a RequestContext attribute, if necessary.
	 * Delegates to renderMergedOutputModel for the actual rendering.
	 * @see #renderMergedOutputModel
	 */
	@Override
	public void render(@Nullable Map<String, ?> model, HttpServletRequest request,
			HttpServletResponse response) throws Exception {

		if (logger.isDebugEnabled()) {
			logger.debug("View " + formatViewName() +
					", model " + (model != null ? model : Collections.emptyMap()) +
					(this.staticAttributes.isEmpty() ? "" : ", static attributes " + this.staticAttributes));
		}

		Map<String, Object> mergedModel = createMergedOutputModel(model, request, response);
		prepareResponse(request, response);
		renderMergedOutputModel(mergedModel, getRequestToExpose(request), response);
	}

	protected abstract void renderMergedOutputModel(
			Map<String, Object> model, HttpServletRequest request, HttpServletResponse response) throws Exception;

InternalResourceView

	/**
	 * Render the internal resource given the specified model.
	 * This includes setting the model as request attributes.
	 */
	@Override
	protected void renderMergedOutputModel(
			Map<String, Object> model, HttpServletRequest request, HttpServletResponse response) throws Exception {

		// Expose the model object as request attributes.
		// 暴露model中的数据到 request域中
		exposeModelAsRequestAttributes(model, request);

		// Expose helpers as request attributes, if any.
		exposeHelpers(request);

		// Determine the path for the request dispatcher.
		String dispatcherPath = prepareForRendering(request, response);

		// Obtain a RequestDispatcher for the target resource (typically a JSP).
		RequestDispatcher rd = getRequestDispatcher(request, dispatcherPath);
		if (rd == null) {
			throw new ServletException("Could not get RequestDispatcher for [" + getUrl() +
					"]: Check that the corresponding file exists within your web application archive!");
		}

		// If already included or response already committed, perform include, else forward.
		if (useInclude(request, response)) {
			response.setContentType(getContentType());
			if (logger.isDebugEnabled()) {
				logger.debug("Including [" + getUrl() + "]");
			}
			rd.include(request, response);
		}

		else {
			// Note: The forwarded resource is supposed to determine the content type itself.
			if (logger.isDebugEnabled()) {
				logger.debug("Forwarding to [" + getUrl() + "]");
			}
			// 页面跳转
			rd.forward(request, response);
		}
	}	

  renderMergedOutputModel方法完成数据渲染和页面跳转

AbstractView

	/**
	 * Expose the model objects in the given map as request attributes.
	 * Names will be taken from the model Map.
	 * This method is suitable for all resources reachable by {@link javax.servlet.RequestDispatcher}.
	 * @param model a Map of model objects to expose
	 * @param request current HTTP request
	 */
	protected void exposeModelAsRequestAttributes(Map<String, Object> model,
			HttpServletRequest request) throws Exception {

		model.forEach((name, value) -> {
			if (value != null) {
				request.setAttribute(name, value);
			}
			else {
				request.removeAttribute(name);
			}
		});
	}	

  把modelMap中的数据暴露到request域中,这也是为什么后台model.add之后再jsp中可以从请求域中取出来的根本原因。

五、Spring MVC九大组件初始化

5.1 九大组件有哪些?

  在 DispatcherServlet 中定义了九个属性,每一个属性都对应一种组件

	/** MultipartResolver used by this servlet. */
	// 多部件解析器
	@Nullable
	private MultipartResolver multipartResolver;
	
	/** LocaleResolver used by this servlet. */
	// 区域化 国际化解析器
	@Nullable
	private LocaleResolver localeResolver;
	
	/** ThemeResolver used by this servlet. */
	// 主题解析器
	@Nullable
	private ThemeResolver themeResolver;
	
	/** List of HandlerMappings used by this servlet. */
	// 处理器映射器组件
	@Nullable
	private List<HandlerMapping> handlerMappings;
	
	/** List of HandlerAdapters used by this servlet. */
	// 处理器适配器组件
	@Nullable
	private List<HandlerAdapter> handlerAdapters;
	
	/** List of HandlerExceptionResolvers used by this servlet. */
	// 异常解析器组件
	@Nullable
	private List<HandlerExceptionResolver> handlerExceptionResolvers;
	
	/** RequestToViewNameTranslator used by this servlet. */
	// 默认视图名转换器组件
	@Nullable
	private RequestToViewNameTranslator viewNameTranslator;
	
	/** FlashMapManager used by this servlet. */
	// flash属性管理组件
	@Nullable
	private FlashMapManager flashMapManager;
	
	/** List of ViewResolvers used by this servlet. */
	// 视图解析器
	@Nullable
	private List<ViewResolver> viewResolvers;

  九大组件都是定义了接口,接口其实就是定义了该组件的规范,比如ViewResolver、HandlerAdapter等都是接口。

5.2 九大组件初始化时机

  在DispatcherServlet 中的 onRefresh() 方法中初始化了九大组件。

DispatcherServlet

	/**
	 * This implementation calls {@link #initStrategies}.
	 */
	@Override
	protected void onRefresh(ApplicationContext context) {
		// 初始化策略
		initStrategies(context);
	}

	/**
	 * Initialize the strategy objects that this servlet uses.
	 * <p>May be overridden in subclasses in order to initialize further strategy objects.
	 * 初始化策略
	 */
	protected void initStrategies(ApplicationContext context) {
		// 多文件上传的组件
		initMultipartResolver(context);
		// 初始化本地语言环境
		initLocaleResolver(context);
		// 初始化模板处理器
		initThemeResolver(context);
		// 初始化HandlerMapping
		initHandlerMappings(context);
		// 初始化参数适配器
		initHandlerAdapters(context);
		// 初始化异常拦截器
		initHandlerExceptionResolvers(context);
		// 初始化视图预处理器
		initRequestToViewNameTranslator(context);
		// 初始化视图转换器
		initViewResolvers(context);
		// 初始化 FlashMap 管理器
		initFlashMapManager(context);
	}

  九大组件的初始化动作都大同小异,都是从IOC容器中获取组件,如果从IOC容器中获取不到,则会按照默认策略进行注册初始化,默认策略在DispatcherServlet.properties文件中配置。

5.2.1 初始化HandlerMapping

  观察其中的一个组件initHandlerMappings(context)

	/**
	 * Initialize the HandlerMappings used by this class.
	 * <p>If no HandlerMapping beans are defined in the BeanFactory for this namespace,
	 * we default to BeanNameUrlHandlerMapping.
	 */
	private void initHandlerMappings(ApplicationContext context) {
		this.handlerMappings = null;

		if (this.detectAllHandlerMappings) {
			// Find all HandlerMappings in the ApplicationContext, including ancestor contexts.
			// 找到所有的HandlerMapping
			Map<String, HandlerMapping> matchingBeans =
					BeanFactoryUtils.beansOfTypeIncludingAncestors(context, HandlerMapping.class, true, false);
			if (!matchingBeans.isEmpty()) {
				this.handlerMappings = new ArrayList<>(matchingBeans.values());
				// We keep HandlerMappings in sorted order.
				AnnotationAwareOrderComparator.sort(this.handlerMappings);
			}
		}
		else {
			try {
				// 否则在ioc中按照固定名称去找
				HandlerMapping hm = context.getBean(HANDLER_MAPPING_BEAN_NAME, HandlerMapping.class);
				this.handlerMappings = Collections.singletonList(hm);
			}
			catch (NoSuchBeanDefinitionException ex) {
				// Ignore, we'll add a default HandlerMapping later.
			}
		}

		// Ensure we have at least one HandlerMapping, by registering
		// a default HandlerMapping if no other mappings are found.
		if (this.handlerMappings == null) {
			// 最后还为空则按照默认策略生成
			this.handlerMappings = getDefaultStrategies(context, HandlerMapping.class);
			if (logger.isTraceEnabled()) {
				logger.trace("No HandlerMappings declared for servlet '" + getServletName() +
						"': using default strategies from DispatcherServlet.properties");
			}
		}
	}

  如果按照类型和按照固定id从IOC容器中找不到对应组件,则会按照默认策略进行注册初始化,默认策略在DispatcherServlet.properties文件中配置。(HandlerAdapter 和 ViewResolver的初始化也是类似于这样的套路)

	protected <T> List<T> getDefaultStrategies(ApplicationContext context, Class<T> strategyInterface) {
		String key = strategyInterface.getName();
		String value = defaultStrategies.getProperty(key);
		if (value != null) {
			String[] classNames = StringUtils.commaDelimitedListToStringArray(value);
			List<T> strategies = new ArrayList<>(classNames.length);
			for (String className : classNames) {
				try {
					Class<?> clazz = ClassUtils.forName(className, DispatcherServlet.class.getClassLoader());
					Object strategy = createDefaultStrategy(context, clazz);
					strategies.add((T) strategy);
				}
				catch (ClassNotFoundException ex) {
					throw new BeanInitializationException(
							"Could not find DispatcherServlet's default strategy class [" + className +
							"] for interface [" + key + "]", ex);
				}
				catch (LinkageError err) {
					throw new BeanInitializationException(
							"Unresolvable class definition for DispatcherServlet's default strategy class [" +
							className + "] for interface [" + key + "]", err);
				}
			}
			return strategies;
		}
		else {
			return new LinkedList<>();
		}
	}

  其中 defaultStrategies 是一个Properties对象,它的定义以及初始化如下图所示:
在这里插入图片描述
DispatcherServlet.properties

在这里插入图片描述

5.2.2 多部件解析器MultipartResolver初始化

  多部件解析器的初始化必须按照id注册对象(该id为multipartResolver)。

	/**
	 * Initialize the MultipartResolver used by this class.
	 * <p>If no bean is defined with the given name in the BeanFactory for this namespace,
	 * no multipart handling is provided.
	 */
	private void initMultipartResolver(ApplicationContext context) {
		try {
			this.multipartResolver = context.getBean(MULTIPART_RESOLVER_BEAN_NAME, MultipartResolver.class);
			if (logger.isTraceEnabled()) {
				logger.trace("Detected " + this.multipartResolver);
			}
			else if (logger.isDebugEnabled()) {
				logger.debug("Detected " + this.multipartResolver.getClass().getSimpleName());
			}
		}
		catch (NoSuchBeanDefinitionException ex) {
			// Default is no multipart resolver.
			this.multipartResolver = null;
			if (logger.isTraceEnabled()) {
				logger.trace("No MultipartResolver '" + MULTIPART_RESOLVER_BEAN_NAME + "' declared");
			}
		}
	}

在这里插入图片描述

六、onRefresh()何时被调用的?

  思考一个问题,既然 onRefresh() 方法完成了Spring MVC初始化九大组件的过程,那么该方法是什么时候被调用的呢?

  先在onRefresh()方法打个断点,看一下方法调用栈。可以看到onRefresh()方法是ContextRefreshListener(容器刷新监听器)监听到了ContextRefreshEvent(容器刷新事件)时触发调用的。
在这里插入图片描述
  那么ContextRefreshListener(容器刷新监听器)什么时候注册的呢?容器刷新事件ContextRefreshEvent又是什么时候触发的呢?带着这两个问题,我们看一下 onRefresh() 方法的调用过程,如下图:
在这里插入图片描述  从图中我们可以看出服务器启动的时候调用了Servlet的 init() 方法,在这边即调用了HttpServletBean的 init() 方法,在该init() 方法中又调用了FrameworkServlet 的 initServletBean() 方法,在 initServletBean() 方法中调用了initWebApplicationContext() 初始化web容器,该方法又调用了ConfigureAndRefreshWebApplicationContext() 方法,在该方法里面先是注册了ContextRefreshListener监听器,在方法最后调用了容器的 refresh() 方法进行容器的刷新,从而触发了ContextRefreshListener监听器的容器刷新事件,容器监听事件里面做的动作即调用了DispatcherServlet的 onRefresh() 方法进行九大组件的初始化。

FrameworkServlet

	protected void configureAndRefreshWebApplicationContext(ConfigurableWebApplicationContext wac) {
		if (ObjectUtils.identityToString(wac).equals(wac.getId())) {
			// The application context id is still set to its original default value
			// -> assign a more useful id based on available information
			if (this.contextId != null) {
				wac.setId(this.contextId);
			}
			else {
				// Generate default id...
				wac.setId(ConfigurableWebApplicationContext.APPLICATION_CONTEXT_ID_PREFIX +
						ObjectUtils.getDisplayString(getServletContext().getContextPath()) + '/' + getServletName());
			}
		}

		wac.setServletContext(getServletContext());
		wac.setServletConfig(getServletConfig());
		wac.setNamespace(getNamespace());
		
		// 注册ContextRefreshListener 监听器
		wac.addApplicationListener(new SourceFilteringListener(wac, new ContextRefreshListener()));

		// The wac environment's #initPropertySources will be called in any case when the context
		// is refreshed; do it eagerly here to ensure servlet property sources are in place for
		// use in any post-processing or initialization that occurs below prior to #refresh
		ConfigurableEnvironment env = wac.getEnvironment();
		if (env instanceof ConfigurableWebEnvironment) {
			((ConfigurableWebEnvironment) env).initPropertySources(getServletContext(), getServletConfig());
		}

		postProcessWebApplicationContext(wac);
		applyInitializers(wac);
		
		// 刷新容器
		wac.refresh();
	}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值