Spring MVC 核心调用流程( 五 )
::: warning 知识点
invokeHandlerMethod方法主要进行了数据和参数的绑定、创建 ModelAndViewContainer视图容器 , 以及相关初始化工作 。:::
进入 invokeAndHandle方法
所在类:org.springframework.web.servlet.mvc.method.annotation. ServletInvocableHandlerMethod
public void invokeAndHandle(ServletWebRequest webRequest, ModelAndViewContainer mavContainer,Object... providedArgs) throws Exception {// 具体调用逻辑 , 重点看Object returnValue = https://www.isolves.com/it/cxkf/kj/2020-10-10/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);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;}}
进入 invokeForRequest方法
所在类:org.springframework.web.method.support. InvocableHandlerMethod
public Object invokeForRequest(NativeWebRequest request, @Nullable ModelAndViewContainer mavContainer,Object... providedArgs) throws Exception {// 获取参数数组,重点看Object[] args = getMethodArgumentValues(request, mavContainer, providedArgs);if (logger.isTraceEnabled()) {logger.trace("Arguments: " + Arrays.toString(args));}return doInvoke(args);}
进入 getMethodArgumentValues方法
所在类:org.springframework.web.method.support. InvocableHandlerMethod
protected Object[] getMethodArgumentValues(NativeWebRequest request, @Nullable ModelAndViewContainer mavContainer,Object... providedArgs) throws Exception {if (ObjectUtils.isEmpty(getMethodParameters())) {return EMPTY_ARGS;}// 入参的包装类 , 里面包装了参数类型 , 参数名称 , 参数注解等等信息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);args[i] = findProvidedArgument(parameter, providedArgs);if (args[i] != null) {continue;}// 典型的策略模式 , 根据 parameter 能否找到对应参数的处理类 , 能找到就返回trueif (!this.resolvers.supportsParameter(parameter)) {throw new IllegalStateException(formatArgumentError(parameter, "No suitable resolver"));}try {// 具体参数值解析过程,重点看看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 error = ex.getMessage();if (error != null && !error.contains(parameter.getExecutable().toGenericString())) {logger.debug(formatArgumentError(parameter, error));}}throw ex;}}return args;}
进入 resolveArgument方法
所在类:org.springframework.web.method.support. HandlerMethodArgumentResolverComposite
public Object resolveArgument(MethodParameter parameter, @Nullable ModelAndViewContainer mavContainer,NativeWebRequest webRequest, @Nullable WebDataBinderFactory binderFactory) throws Exception {// 根据参数获取对应参数的解析类HandlerMethodArgumentResolver resolver = getArgumentResolver(parameter);if (resolver == null) {throw new IllegalArgumentException("Unsupported parameter type [" + parameter.getParameterType().getName() + "]." +" supportsParameter should be called first.");}// 策略模式去调用具体参数解析类return resolver.resolveArgument(parameter, mavContainer, webRequest, binderFactory);}
::: warning 知识点MethodParameter类是对参数信息的封装 , 其中重要的几个属性包括:
- parameterIndex:参数的索引位置
- Parameter:具体参数的对象 , 包含参数名字
- parameterType:参数的类型
- parameterAnnotations:参数的注解数组 , 一个参数可以有多个注解
- parameterName:参数名 等等 :::
进入 getArgumentResolver方法
所在类:org.springframework.web.method.support. HandlerMethodArgumentResolverComposite
private HandlerMethodArgumentResolver getArgumentResolver(MethodParameter parameter) {// 先从缓存中拿到参数处理器对象HandlerMethodArgumentResolver result = this.argumentResolverCache.get(parameter);// 如果缓存中没有if (result == null) {// 循环容器中 HandlerMethodArgumentResolver类型的所有解析器: List<HandlerMethodArgumentResolver>for (HandlerMethodArgumentResolver methodArgumentResolver : this.argumentResolvers) {// 典型的策略模式匹配 , 拿到当前参数对应的处理解析类if (methodArgumentResolver.supportsParameter(parameter)) {// 赋值给 HandlerMethodArgumentResolver 对象result = methodArgumentResolver;// 放到缓存中this.argumentResolverCache.put(parameter, result);break;}}}return result;}
推荐阅读
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Spring Security 中如何细化权限粒度?
- springcloud微服务架构开发实战:分布式消息总线
- 怎么理解Laravel的核心架构
- 原来这才是Spring Boot使用AOP的正确姿势
- 使用spring cache让我的接口性能瞬间提升了100倍
- Springboot 实现数据库备份还原
- 微服务架构图
- 全网最全一篇数据库MVCC详解,不全你打我
- SpringCloud开发框架入门知识
- SpringMVC:进阶