在Spring中,如果我没有弄错的话,以下两个陈述是相同的:
@RequestParam("type") String type
@RequestParam String type
Spring如何知道'type'的变量名(第二版)。我受到了印象 除非使用编译,否则此信息已从类文件中删除 -g标志(包括调试信息)。
答案 0 :(得分:6)
这个的简短版本显然是在编译参数名称,如果不是,你会得到一个异常,表明Spring MVC无法推断出参数名称。也就是说,参数名称并不总是存储在字节码中,但看起来如果它们是,Spring会找到它们,如果没有,你需要在添加@RequestParam
注释时指定它们。
此similar question提供了其他详细信息,answers。
在3.0.5.RELEASE中,这些注释在HandlerMethodInvoker.resolveHandlerArguments中处理,如果没有提供任何值,Spring似乎使用RequestParam.value()
。这可以返回空字符串。
再往下,Spring使用HandlerMethodInvoker.resolveRequestParam
,并且在那里,如果参数名称为空,则以MethodParameter methodParam
为参数调用HandlerMethodINvoker.getRequiredParameterName
:
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
的一部分,据我所知,尝试从字节码中读取参数名称。