Springs的@RequestParam注释的内部工作

时间:2011-07-31 18:47:25

标签: java spring annotations internal

在Spring中,如果我没有弄错的话,以下两个陈述是相同的:

@RequestParam("type") String type
@RequestParam String type

Spring如何知道'type'的变量名(第二版)。我受到了印象 除非使用编译,否则此信息已从类文件中删除 -g标志(包括调试信息)。

1 个答案:

答案 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的一部分,据我所知,尝试从字节码中读取参数名称。