简而言之,显然参数名称正在被编译,如果没有,您会得到一个异常,表明 Spring MVC 无法推断出参数名称。也就是说,参数名称并不总是存储在字节码中,但似乎如果它们存在,Spring会找到它们,如果没有,则需要在添加时指定它们@RequestParam
注解。
其他详细信息可参见此类似的问题这是answers.
在3.0.5.RELEASE中,这些注释在HandlerMethodInvoker.resolveHandlerArguments如果没有提供任何值,Spring 将使用RequestParam.value()
。这可以返回空字符串。
再往下,Spring 使用HandlerMethodInvoker.resolveRequestParam,在里面,如果参数名称为空,它会调用HandlerMethodINvoker.getRequiredParameterName with MethodParameter methodParam
作为一个论点:
718 private String getRequiredParameterName(MethodParameter methodParam) {
719 String name = methodParam.getParameterName();
720 if (name == null) {
721 throw new IllegalStateException(
722 "No parameter name specified for argument of type [" + methodParam.getParameterType().getName() +
723 "], and no parameter name information found in class file either.");
724 }
725 return name;
726 }
请注意,这里它尝试从中提取信息methodParam
,如果我们备份树,我们会看到resolveHandlerArguments
实际上创建了一个新的MethodParameter对于它处理的每个参数。里面MethodParameter
,我们可以看一下getParameterName():
276 public String getParameterName() {
277 if (this.parameterNameDiscoverer != null) {
278 String[] parameterNames = (this.method != null ?
279 this.parameterNameDiscoverer.getParameterNames(this.method) :
280 this.parameterNameDiscoverer.getParameterNames(this.constructor));
281 if (parameterNames != null) {
282 this.parameterName = parameterNames[this.parameterIndex];
283 }
284 this.parameterNameDiscoverer = null;
285 }
286 return this.parameterName;
287 }
所以这使用了一种叫做ParameterNameDiscoverer,但这是一个接口,我的跟踪没有显示它正在使用哪个实现,有一个few。看着LocalVariableTableParameterNameDiscoverer.getParameterNames我们最终调用了LocalVariableTableParameterNameDiscoverer.ParameterNameDiscoveringVisitor作为一个org.objectweb.asm.ClassReader,据我所知,它尝试从字节码中读取参数名称。