Springs @RequestParam 注解的内部工作原理
在 Spring 中,如果我没记错的话,以下两个语句是相同的:
@RequestParam("type") String type
@RequestParam String type
Spring 如何知道“type”的变量名称(第二个版本)。我当时的印象是 该信息已从类文件中删除,除非使用 -g 标志(包括调试信息)。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
简而言之,显然参数名称正在被编译,如果没有,您会得到一个异常,表明 Spring MVC 无法推断出参数名称。也就是说,参数名称并不总是存储在字节码中,但似乎如果是,Spring 会找到它们,如果不是,则需要在添加
@RequestParam
注解时指定它们。其他详细信息可参见此类似问题,它是答案。
在3.0.5.RELEASE中,这些注释在 HandlerMethodInvoker.resolveHandlerArguments ,如果没有提供任何值,Spring 将使用
RequestParam.value()
。这可以返回空字符串。再往下,Spring 使用
HandlerMethodInvoker.resolveRequestParam
,其中,如果参数名称为空,则会调用HandlerMethodINvoker.getRequiredParameterName
以MethodParameter methodParam
作为参数:请注意,这里它尝试从
methodParam
中提取信息,如果我们备份树,我们会看到resolveHandlerArguments
实际上创建了一个新的MethodParameter
对于它处理的每个参数。在MethodParameter
中,我们可以看一下getParameterName()
:所以这使用了名为
ParameterNameDiscoverer
,但这是一个接口,我的跟踪没有显示它是哪个实现使用,有很少。查看 LocalVariableTableParameterNameDiscoverer.getParameterNames 我们最终调用了LocalVariableTableParameterNameDiscoverer.ParameterNameDiscoveringVisitor
作为org.objectweb.asm.ClassReader
,据我所知,它尝试从字节码中读取参数名称。The short version of this is that apparently the parameter names are being compiled in, if they weren't, you'd get an exception indicating that Spring MVC couldn't deduce the parameter name. That is, parameter names aren't always stored in the bytecode, but it seems like if they are, Spring will find them, if not, you need to specify them when you add the
@RequestParam
annotation.Other details are available on this similar question and it's answers.
In 3.0.5.RELEASE, these annotations are processed in HandlerMethodInvoker.resolveHandlerArguments and it appears that if no value is supplied, Spring uses
RequestParam.value()
. This can return the empty string.Further down, Spring uses
HandlerMethodInvoker.resolveRequestParam
, and inside there, if the parameter name is empty, it invokesHandlerMethodINvoker.getRequiredParameterName
withMethodParameter methodParam
as an argument:Note that here it tries to pull the information from
methodParam
, which, if we back up the tree, we see thatresolveHandlerArguments
actually creates a newMethodParameter
for each argument that it processes. InsideMethodParameter
, we can take a look atgetParameterName()
:So this uses something called a
ParameterNameDiscoverer
, but this is an interface and my trace isn't showing which implementation it's using, there are a few. Looking at LocalVariableTableParameterNameDiscoverer.getParameterNames we end up calling aLocalVariableTableParameterNameDiscoverer.ParameterNameDiscoveringVisitor
as part of anorg.objectweb.asm.ClassReader
, which as far as I can tell tries to read the parameter name out of the bytecode.