扩充源码:深入研究SpringMVC数据绑定过程
接下来进入debug模式,看看mvc是如何将我们request中的参数绑定到我们controller层方法入参的;
写一个简单controller,打个断点看看方法调用栈:
@GetMapping("/getDate")
public LocalDateTime getDate(@RequestParam LocalDate date,
@RequestParam LocalDateTime dateTime,
@RequestParam Date originalDate) {
System.out.println(date);
System.out.println(dateTime);
System.out.println(originalDate);
return LocalDateTime.now();
}
调用接口以后,我们看下方法调用栈中一些关键方法:
//进入DispatcherServlet doService:942, DispatcherServlet //处理请求 doDispatch:1038, DispatcherServlet //生成调用链(前处理、实际调用方法、后处理) handle:87, AbstractHandlerMethodAdapter //反射获取到实际调用方法,准备开始调用 invokeHandlerMethod:895, RequestMappingHandlerAdapter invokeAndHandle:102, ServletInvocableHandlerMethod //这里是关键,参数从这里开始获取到 invokeForRequest:142, InvocableHandlerMethod doInvoke:215, InvocableHandlerMethod //这个是Java reflect调用,因此一定是在这之前获取到的参数 invoke:566, Method
根据上述分析,发现invokeForRequest:142, InvocableHandlerMethod这里的代码是用来拿到实际参数的:
@Nullable
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);
}
进入这个方法看看是什么操作:
protected Object[] getMethodArgumentValues(NativeWebRequest request, @Nullable ModelAndViewContainer mavContainer, Object... providedArgs) throws Exception {
//获取方法参数数组,包含了入参信息,比如类型、泛型等等
MethodParameter[] parameters = getMethodParameters();
//这个用来存放一会从request parameter转换的参数
Object[] args = new Object[parameters.length];
for (int i = 0; i < parameters.length; i++) {
MethodParameter parameter = parameters[i];
parameter.initParameterNameDiscovery(this.parameterNameDiscoverer);
//这里看起来没啥卵用(providedArgs为空)
args[i] = resolveProvidedArgument(parameter, providedArgs);
//这里开始获取到方法实际调用的参数,步进
if (this.argumentResolvers.supportsParameter(parameter)) {
//从名字就看出来:参数解析器解析参数
args[i] = this.argumentResolvers.resolveArgument(parameter, mavContainer, request, this.dataBinderFactory);
continue;
}
}
return args;
}










