文章目录

  • 本文简略
  • doservice方法
  • doDispatch(重要)
  • HandlerExecutionChain执行链
  • 获取HandlerExecutionChain执行链
  • 获取处理器适配器HandlerAdapter
  • RequestMappingHandlerAdapter执行handle方法
  • 调用方法:invokeAndHandle
  • 调用方法invokeForRequest
  • getMethodArgumentValues获取参数解析
  • resolveArgument,调用参数解析器的解析方法
  • 扩展



springmvc源码解析(三),DispatcherServlet主要处理请求流程_初始化

本文简略

这篇文章主要讲doDispatch方法对请求的处理, //实际的处理器处理请求,返回结果视图对象;视图对象的处理下篇再看.这是springmvc处理请求的核心中的核心.建议反复观看.

doservice方法

DispatcherServlet中最主要的核心功能是由doService和doDispatch实现的。

当请求到达后HttpServlet将调用service方法进行处理,由于我们是通过输入网址方式的get方法请求,Servlet将调用doGet方法

此处的doGet方法在FrameworkServlet中实现,doGet方法调用processRequest方法,

processRequest则调用doService方法处理,而doService在DispatcherServlet中实现,

doService再调用了DispatcherServlet的doDispatch方法,该方法则会根据request找到转发对象,并进行请求转发操作,

即dispatcherservlet中无论是通过post方式还是get方式提交的request,最终都会交由doservice()处理,然后交给doDispatch方法执行.

doService方法就如果是include请求然后保存一份快照版本中的域,还有request域中设置一些属性.

@Override
	protected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception {
		if (logger.isDebugEnabled()) {
			String resumed = WebAsyncUtils.getAsyncManager(request).hasConcurrentResult() ? " resumed" : "";
			logger.debug("DispatcherServlet with name '" + getServletName() + "'" + resumed +
					" processing " + request.getMethod() + " request for [" + getRequestUri(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<String, Object>();
			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());

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

doDispatch(重要)

doDispatch方法是处理请求的核心方法,主要流程就是判断是否上传接口,然后根据请求路径找到封装了handler和interceptors的对象HandlerExecutionChain,得到HandlerExecutionChain之后通过适配器HandlerAdapter处理得到ModelAndView对象,处理器映射器,处理器适配器前面初始化的时候都初始化了,处理器适配器的使用就在这里说.如果发生异常则会被HandlerExceptionResolver接口实现类进行处理;

// 中央控制器,控制请求的转发
	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 {
				//检查是否是文件上传的请求
				processedRequest = checkMultipart(request);
				multipartRequestParsed = (processedRequest != request);

				// Determine handler for the current request.
				// 获取当前骑牛的controller,,这里也称为hanlder,处理器,第一个步骤的意义就在这里体现了.这里并不是直接返回controller,
				// 而是返回的HandlerExecutionChain请求处理器链对象,该对象封装了handler和interceptors.
				mappedHandler = getHandler(processedRequest);
				//handler为空返回404
				if (mappedHandler == null || mappedHandler.getHandler() == null) {
					noHandlerFound(processedRequest, response);
					return;
				}

				// Determine handler adapter for the current request.
				//获取处理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.
				//实际的处理器处理请求,返回结果视图对象
				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);
				}
			}
		}
	}

HandlerExecutionChain执行链

我们先看HandlerExecutionChain执行链,当拿到执行链的时候,就已经完成了request到controller的路由匹配,拦截器链,则是很多个拦截器组成连链,拦截器都知道,就是在执行我们的handler之前之后执行,就是一个aop的简单实现:

springmvc源码解析(三),DispatcherServlet主要处理请求流程_sed_02

获取HandlerExecutionChain执行链

前面讲了初始化handlerMapping,其中最重要的最常用的就是RequestMappingHandlerMapping,就是通过Controller注解配置的类使用RequestMapping注解配置的方法,handlerMappings里面是通过不同方式配置的controller类,需要不同的handlerMapping类处理,前一篇文章也说了:
RequestMappingHandlerAdapter->
通过@Controller配置类@RequestMapping注解配置的方法
SimpleUrlHandlerMapping->
实现Controller类重写handlerRequest方法

<bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
            <property name="mappings">
                <props>
                    <prop key="index">TestController</prop>
                </props>
            </property>
        </bean>
    
        <bean id="TestController" class="com.alipay.web.TestController" />

BeanNameUrlHandlerMapping->
类实现Controller,重写handlerRequest()方法即可

<bean id="/index" class="com.alipay.web.TestController" />

springmvc源码解析(三),DispatcherServlet主要处理请求流程_java_03


比较重要的就是获取handler对象了,我们看getHandlerInternal方法,这个方法返回了HandlerMethod对象,这个对象就是被@ RequestMapping 注解封装的方法模型类;

通过url找到urlLookup这个map中对应的handler, 然后根据一些匹配规则, 返回一个最优的 (urlLookup这个map中的键值对是在init初始化的时候, 通过反射解析放进去的), 到此为止可以知道: 我们可以通过url获取到具体的handlerMethod对象:

public class HandlerMethod {

	/** Logger that is available to subclasses */
	protected final Log logger = LogFactory.getLog(getClass());
	// Object类型,可以是Bean,也可以是个String 的 BeanName
	private final Object bean;
	//bean工厂
	private final BeanFactory beanFactory;
	//方法对应的Class类
	private final Class<?> beanType;
	// 该方法
	private final Method method;
	// 桥接方法
	private final Method bridgedMethod;
	//方法参数的入参
	private final MethodParameter[] parameters;

	private HttpStatus responseStatus;

	private String responseStatusReason;

	//通过createWithResolvedBean()解析此handlerMethod实例的handlerMethod。
	private HandlerMethod resolvedFromHandlerMethod;

lookupHandlerMethod方法:

protected HandlerMethod lookupHandlerMethod(String lookupPath, HttpServletRequest request) throws Exception {
		List<Match> matches = new ArrayList<Match>();
		//通过url找到对应的handler,然后通过匹配规则,返回最优的
		List<T> directPathMatches = this.mappingRegistry.getMappingsByUrl(lookupPath);
		if (directPathMatches != null) {
			addMatchingMappings(directPathMatches, matches, request);
		}
		if (matches.isEmpty()) {
			// No choice but to go through all mappings...
			addMatchingMappings(this.mappingRegistry.getMappings().keySet(), matches, request);
		}

		if (!matches.isEmpty()) {
			Comparator<Match> comparator = new MatchComparator(getMappingComparator(request));
			Collections.sort(matches, comparator);
			if (logger.isTraceEnabled()) {
				logger.trace("Found " + matches.size() + " matching mapping(s) for [" +
						lookupPath + "] : " + matches);
			}
			Match bestMatch = matches.get(0);
			if (matches.size() > 1) {
				if (CorsUtils.isPreFlightRequest(request)) {
					return PREFLIGHT_AMBIGUOUS_MATCH;
				}
				Match secondBestMatch = matches.get(1);
				if (comparator.compare(bestMatch, secondBestMatch) == 0) {
					Method m1 = bestMatch.handlerMethod.getMethod();
					Method m2 = secondBestMatch.handlerMethod.getMethod();
					throw new IllegalStateException("Ambiguous handler methods mapped for HTTP path '" +
							request.getRequestURL() + "': {" + m1 + ", " + m2 + "}");
				}
			}
			request.setAttribute(BEST_MATCHING_HANDLER_ATTRIBUTE, bestMatch.handlerMethod);
			handleMatch(bestMatch.mapping, lookupPath, request);
			return bestMatch.handlerMethod;
		}
		else {
			return handleNoMatch(this.mappingRegistry.getMappings().keySet(), lookupPath, request);
		}
	}

然后根据HandlerMethod对象封装成HandlerExecutionChain对象返回:

protected HandlerExecutionChain getHandlerExecutionChain(Object handler, HttpServletRequest request) {
		HandlerExecutionChain chain = (handler instanceof HandlerExecutionChain ?
				(HandlerExecutionChain) handler : new HandlerExecutionChain(handler));

		String lookupPath = this.urlPathHelper.getLookupPathForRequest(request);
		for (HandlerInterceptor interceptor : this.adaptedInterceptors) {
			if (interceptor instanceof MappedInterceptor) {
				MappedInterceptor mappedInterceptor = (MappedInterceptor) interceptor;
				if (mappedInterceptor.matches(lookupPath, this.pathMatcher)) {
					chain.addInterceptor(mappedInterceptor.getInterceptor());
				}
			}
			else {
				chain.addInterceptor(interceptor);
			}
		}
		return chain;
	}

获取处理器适配器HandlerAdapter

根据handler获取适配器,如果没有匹配到handler,则会执行noHandlerFound返回404,会打印日志No mapping found for HTTP request with URI:

springmvc源码解析(三),DispatcherServlet主要处理请求流程_sed_04


获取适配器就是根据适配器list进行遍历获取合适的适配器,前面适配器也大概讲了一下,跟映射器差不多,对应的解析器也是根据实现方法走不同的适配器,然后通过适配器适配处理过后执行handler方法:

实现controller接口的对应->SimpleControllerHandlerAdapter
实现HttpRequestHandler接口的对应->HttpRequestHandlerAdapter
通过@RequestMapping注解扫描:RequestMappingHandlerAdapter

其他两个就执行对应的方法,我们主要讲通过注解的方式请求处理,获取到适配器就要执行handler方法了:

springmvc源码解析(三),DispatcherServlet主要处理请求流程_初始化_05

RequestMappingHandlerAdapter执行handle方法

handler方法就是调用handleInternal方法,强转了一下:handleInternal方法就判断是否是要串行化访问,如果串行化则要进行加锁处理,然后最终都是执行invokeHandlerMethod方法:

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

		//将request和response包装成ServletWebRequest对象
		ServletWebRequest webRequest = new ServletWebRequest(request, response);
		try {
			//返回Web数据绑定器工厂
			WebDataBinderFactory binderFactory = getDataBinderFactory(handlerMethod);
			//获取模型工厂
			ModelFactory modelFactory = getModelFactory(handlerMethod, binderFactory);

			//返回要调用的方法
			ServletInvocableHandlerMethod invocableMethod = createInvocableHandlerMethod(handlerMethod);
			// 设置参数解析
			invocableMethod.setHandlerMethodArgumentResolvers(this.argumentResolvers);
			//设置返回类型解析
			invocableMethod.setHandlerMethodReturnValueHandlers(this.returnValueHandlers);
			//设置web数据绑定工厂
			invocableMethod.setDataBinderFactory(binderFactory);
			//设置参数发现器,查找方法的参数名称
			invocableMethod.setParameterNameDiscoverer(this.parameterNameDiscoverer);

			//创建modelandView容器
			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);
			//设置Callable任务的带有延迟的拦截器
			asyncManager.registerDeferredResultInterceptors(this.deferredResultInterceptors);

			if (asyncManager.hasConcurrentResult()) {
				Object result = asyncManager.getConcurrentResult();
				mavContainer = (ModelAndViewContainer) asyncManager.getConcurrentResultContext()[0];
				asyncManager.clearConcurrentResult();
				if (logger.isDebugEnabled()) {
					logger.debug("Found concurrent result value [" + result + "]");
				}
				invocableMethod = invocableMethod.wrapConcurrentResult(result);
			}

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

			//返回modelandView
			return getModelAndView(mavContainer, modelFactory, webRequest);
		}
		finally {
			webRequest.requestCompleted();
		}
	}

调用方法:invokeAndHandle

public void invokeAndHandle(ServletWebRequest webRequest, ModelAndViewContainer mavContainer,
			Object... providedArgs) throws Exception {

		// 调用方法获取返回参数
		Object returnValue = invokeForRequest(webRequest, mavContainer, providedArgs);
		setResponseStatus(webRequest);

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

		mavContainer.setRequestHandled(false);
		try {
			//处理返回参数
			this.returnValueHandlers.handleReturnValue(
					returnValue, getReturnValueType(returnValue), mavContainer, webRequest);
		}
		catch (Exception ex) {
			if (logger.isTraceEnabled()) {
				logger.trace(getReturnValueHandlingErrorMessage("Error handling return value", returnValue), ex);
			}
			throw ex;
		}
	}

调用方法invokeForRequest

这个方法比较重要,有获取请求参数,getMethodArgumentValues,然后获取了参数就直接调用反射调用对应方法就行了,主要介绍参数解析:

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

		//获取请求参数
		Object[] args = getMethodArgumentValues(request, mavContainer, providedArgs);
		if (logger.isTraceEnabled()) {
			logger.trace("Invoking '" + ClassUtils.getQualifiedMethodName(getMethod(), getBeanType()) +
					"' with arguments " + Arrays.toString(args));
		}
		// 执行方法
		Object returnValue = doInvoke(args);
		if (logger.isTraceEnabled()) {
			logger.trace("Method [" + ClassUtils.getQualifiedMethodName(getMethod(), getBeanType()) +
					"] returned [" + returnValue + "]");
		}
		return returnValue;
	}

getMethodArgumentValues获取参数解析

private Object[] getMethodArgumentValues(NativeWebRequest request, ModelAndViewContainer mavContainer,
			Object... providedArgs) throws Exception {

		// 获取方法参数
		MethodParameter[] parameters = getMethodParameters();
		Object[] args = new Object[parameters.length];
		for (int i = 0; i < parameters.length; i++) {
			MethodParameter parameter = parameters[i];
			// 初始化参数名的发现器
			parameter.initParameterNameDiscovery(this.parameterNameDiscoverer);
			// 解析,一般为null
			args[i] = resolveProvidedArgument(parameter, providedArgs);
			if (args[i] != null) {
				continue;
			}
			//查找对应的参数的处理器,主要是遍历所有的参数的处理器,调用处理中的support方法,只要满足就返回true,放到缓存中
			if (this.argumentResolvers.supportsParameter(parameter)) {
				try {
					//调用放到缓存中的参数解析器,然后调用resolveArgument解析对象
					args[i] = this.argumentResolvers.resolveArgument(
							parameter, mavContainer, request, this.dataBinderFactory);
					continue;
				}
				catch (Exception ex) {
					if (logger.isDebugEnabled()) {
						logger.debug(getArgumentResolutionErrorMessage("Failed to resolve", i), ex);
					}
					throw ex;
				}
			}
			if (args[i] == null) {
				throw new IllegalStateException("Could not resolve method parameter at index " +
						parameter.getParameterIndex() + " in " + parameter.getMethod().toGenericString() +
						": " + getArgumentResolutionErrorMessage("No suitable resolver for", i));
			}
		}
		return args;
	}

supportsParameter验证是否有对应的参数解析器:

springmvc源码解析(三),DispatcherServlet主要处理请求流程_springmvc_06

获取参数解析器方法getArgumentResolver:

private HandlerMethodArgumentResolver getArgumentResolver(MethodParameter parameter) {
		//从缓存中取,没有就遍历所有的
		HandlerMethodArgumentResolver result = this.argumentResolverCache.get(parameter);
		if (result == null) {
			// 遍历所有参数解析器对参数进行适配,supportsParameter如果返回true,就是适配成功
			for (HandlerMethodArgumentResolver resolver : this.argumentResolvers) {
				if (resolver.supportsParameter(parameter)) {
					result = resolver;
					this.argumentResolverCache.put(parameter, result);
					break;
				}
			}
		}
		return result;
	}

resolveArgument,调用参数解析器的解析方法

springmvc源码解析(三),DispatcherServlet主要处理请求流程_springmvc_07

我们看最常用的通过@RequestParam注解标注的参数解析,使用的解析器是RequestParamMethodArgumentResolver,我们主要讲这个类,其他都差不多.

springmvc源码解析(三),DispatcherServlet主要处理请求流程_初始化_08

springmvc源码解析(三),DispatcherServlet主要处理请求流程_springmvc_09


然后调用抽象类AbstractNamedValueMethodArgumentResolver的resolveArgument方法:

@Override
	public final Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer,
			NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {

		//获取名称
		NamedValueInfo namedValueInfo = getNamedValueInfo(parameter);
		//获取参数类型
		MethodParameter nestedParameter = parameter.nestedIfOptional();

		//解析字符串值
		Object resolvedName = resolveStringValue(namedValueInfo.name);
		if (resolvedName == null) {
			throw new IllegalArgumentException(
					"Specified name must not resolve to null: [" + namedValueInfo.name + "]");
		}

		//调用子类方法解析参数
		Object arg = resolveName(resolvedName.toString(), nestedParameter, webRequest);
		if (arg == null) {
			//是否有默认值
			if (namedValueInfo.defaultValue != null) {
				arg = resolveStringValue(namedValueInfo.defaultValue);
			}
			//是否必填
			else if (namedValueInfo.required && !nestedParameter.isOptional()) {
				handleMissingValue(namedValueInfo.name, nestedParameter, webRequest);
			}
			//处理空值
			arg = handleNullValue(namedValueInfo.name, arg, nestedParameter.getNestedParameterType());
		}
		else if ("".equals(arg) && namedValueInfo.defaultValue != null) {
			arg = resolveStringValue(namedValueInfo.defaultValue);
		}

		//对参数进行转换,一般接收都是String类型,换成对应的类型
		if (binderFactory != null) {
			WebDataBinder binder = binderFactory.createBinder(webRequest, null, namedValueInfo.name);
			try {
				arg = binder.convertIfNecessary(arg, parameter.getParameterType(), parameter);
			}
			catch (ConversionNotSupportedException ex) {
				throw new MethodArgumentConversionNotSupportedException(arg, ex.getRequiredType(),
						namedValueInfo.name, parameter, ex.getCause());
			}
			catch (TypeMismatchException ex) {
				throw new MethodArgumentTypeMismatchException(arg, ex.getRequiredType(),
						namedValueInfo.name, parameter, ex.getCause());

			}
		}

		//空方法
		handleResolvedValue(arg, namedValueInfo.name, parameter, mavContainer, webRequest);

		return arg;
	}

resolveName调用子类RequestParamMethodArgumentResolver的方法resolveName:

springmvc源码解析(三),DispatcherServlet主要处理请求流程_springmvc_10


到这,请求参数就都封装完成了,然后就是通过反射调用方法了.

扩展

在获取NamedValueInfo 的时候有个知识点,springmvc不使用注解@RequestParam(“i”)标注的参数,springmvc也能进行封装,而mybatis编写mapper的时候必须要带上@Param接口,springmvc是怎么做到的:

//获取名称

NamedValueInfo namedValueInfo = getNamedValueInfo(parameter);

springmvc源码解析(三),DispatcherServlet主要处理请求流程_初始化_11


springmvc源码解析(三),DispatcherServlet主要处理请求流程_sed_12


然后就会走到LocalVariableTableParameterNameDiscoverer这个类的getParameterNames方法,通过asm框架去解析获取参数:

springmvc源码解析(三),DispatcherServlet主要处理请求流程_拦截器_13


springmvc源码解析(三),DispatcherServlet主要处理请求流程_初始化_14

所以尽量使用注解,这样可以省去通过asm框架重新加载字节码文件,使用jdk1.8包括之后的版本java反射也增加了存储方法名的类,但是需要配置,这里不做过多描述了