前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >参数注解所引发的思考

参数注解所引发的思考

作者头像
每天学Java
发布2020-09-01 15:18:36
6920
发布2020-09-01 15:18:36
举报
文章被收录于专栏:每天学Java每天学Java

Java Web开发人员应该十分熟悉Spring MVC中@PathVariable、@RequestParam、以及MyBatis@Param注解,这类注解的值通常和我们参数名称相同, 我们也可以使用这些参数注解去设置别名,而本篇文章也是由参数注解的使用引发的一系列思考。

在刚接触Spring MVC的时候,个人认为类似@Param注解的作用是用来匹配参数,像 Spring MVC的Controller层的方法是通过反射来实现的,细心的小伙伴们如果对反射机制比较了解, 就会知道通过反射得到的方法参数通常是arg0、arg1......这种格式,出现这种结果的原因是:设计人员认为保留参数名称,不会带来任何好处,只会占用额外的空间,所以出于性能考虑,就没有保留参数名称。所以在刚工作那会我一直认为注解值就是为了匹配参数名称的, 甚至每次注解上设置的别名都不敢和参数名不一样,但是在后续工作中,我们会发现不使用注解,只要请求的参数和方法参数名称相同,仍然是能匹配上的,匹配上的原因也是本篇文章要说明的重点。

随着Spring的兴起,反射的使用变得十分广泛, JDK1.8开始开始在class文件中保留参数名(需要手动设置-parameters),给反射带来了极大的便利,如下图,我们在IDEA中设置-parameters那么反射获取的参数名称就不会是arg0的格式。

上面我们说-parameters只适用于jdk1.8以后,那么在jdk1.8之前Spring是如何将我们请求的参数和arg0匹配上呢

方案一:注解

首先就是参数注解的作用了,也是我们最熟悉的方式,通过注解设置的别名来匹配请求的参数,当URL匹配到Method方法时,我们从注解参数中获取参数名称,如下代码(截自https://github.com/xynuSuMu/jerry.git):

代码语言:javascript
复制
Param param;
else if ((param = parameter.getDeclaredAnnotation(Param.class))
            != null) {
        params[i++] = httpJerryRequest.getParameter(param.value());
}

方案二:字节码工具

如果我们没有使用注解,Spring就会无法匹配参数吗,显然不是,强大的Spring已经考虑过这种情况的发生。在JDK1.8之前虽然反射无法直接获取到参数名称,但是如果我们使用-g或者-g:vars参数,编译就会生成了调试信息, class文件中会生成方法参数名信息(在本地变量表LocalVariableTable中),所以通过字节码工具,我们仍然能获取到方法参数,这也是Spring获取参数名称所采用的方法,也许小伙伴们很疑惑, 我并不记得我又设置过-g这个参数啊,实际上此设置通常是默认的,比如在IDEA开发工具中,该选项是默认勾选的,下图的第二个选项: Generate debugging info

如果我们没有使用注解,那么Spring就会去 本地变量表中获取相关的参数信息。

那么我们也可以知道如果在非JDK8版本下,或者JDK8版本后未使用-parameters注解,那么我们取消勾选上面的选项后,重新编译代码, 接口调用就会报错

此外,如果大家在JDK8以下的版本中,又使用的是非Spring项目,此时又需要参数名称,那么在开启上述的配置之后,可以考虑集成ASM来获取参数名称。而在JDK8版本后,我们就不必使用ASM或者其他手段从字节码中获取参数名称了,只需要使用-parameters即可。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2020-08-31,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 每天学Java 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档