背景
今天测试环境出现了一个错误,错误原因很简单,Mybatis Mapper文件在传递参数的时候没有使用 Param注解。 在Mybatis中,如果要传递多个参数必须使用 @Param 注解,否则会出现获取参数失败的情况。
作为一个有点懒惰的开发,我是希望把 @Param 注解去掉的,于是我去Github Mybatis的issue搜索了一圈,发现也有同学有这样的问题和需求。
于是我就开始想,为什么SpringMVC可以获取到参数,而Mybatis就不行呢,于是我打算用ASM获取一下参数(SpringMVC是使用ASM来做的),我立马就把以前的代码Copy过来
- 调试一下带body的方法,跑通了。
- 又测试了一个Interface,失败了。
调试
于是在休息的时候,我开始对ASM的过程进行debug,使用过ASM的同学都知道,他是对class文件进行依次visit处理的过程,结果却发现interface的method压根就进不去哪些方法,直接来到了visitEnd. 自然就获取不到参数了。
我马上开始Google, 中文网上都是对ASM的介绍,于是我又去stackoverflow查看问题,果然被我查到了。但是这里的结论只是描述了interface的method是不行的,但是为什么不行,则没有进行描述。这个有点不符合stackoverflow的提问哲学。
emmmmm,我最后把我的发现结果回复了这个问题,还迎来了2个反对,丢失了4分,得不偿失,得不偿失呀 🤣🤣🤣🤣🤣🤣🤣
果然我遇到的问题,都有人遇到过了。
我又想到ASM issue去看看什么情况,但是也没有找到问题,在找的过程中,猛滴想到ASM本身就是解析class文件的, 于是使用javap查看情况。
public interface FF {default void hh(String name) {}String hello(String hello);}
Javap执行结果,如下所示,interface的hello方法,是没有body体的,同时也没有LocalVariableTable,而我如果要获取参数,就必须以来这里的LocalVariableTable。所以我无法获取到参数,只能通过注解来实现。
➜ ~ javap -v /Users/chenshun/tool/winter/target/test-classes/io/github/chenshun00/web/asm/FF.classClassfile /Users/chenshun/tool/winter/target/test-classes/io/github/chenshun00/web/asm/FF.classLast modified 2022-7-15; size 384 bytesMD5 checksum de24290be11cb7706f83d3a355261367Compiled from "FF.java"public interface io.github.chenshun00.web.asm.FFminor version: 0major version: 52flags: ACC_PUBLIC, ACC_INTERFACE, ACC_ABSTRACTConstant pool:#1 = Class #16 // io/github/chenshun00/web/asm/FF#2 = Class #17 // java/lang/Object#3 = Utf8 hh#4 = Utf8 (Ljava/lang/String;)V#5 = Utf8 Code#6 = Utf8 LineNumberTable#7 = Utf8 LocalVariableTable#8 = Utf8 this#9 = Utf8 Lio/github/chenshun00/web/asm/FF;#10 = Utf8 name#11 = Utf8 Ljava/lang/String;#12 = Utf8 hello#13 = Utf8 (Ljava/lang/String;)Ljava/lang/String;#14 = Utf8 SourceFile#15 = Utf8 FF.java#16 = Utf8 io/github/chenshun00/web/asm/FF#17 = Utf8 java/lang/Object{public void hh(java.lang.String);descriptor: (Ljava/lang/String;)Vflags: ACC_PUBLICCode:stack=0, locals=2, args_size=20: returnLineNumberTable:line 17: 0LocalVariableTable:Start Length Slot Name Signature0 1 0 this Lio/github/chenshun00/web/asm/FF;0 1 1 name Ljava/lang/String;public abstract java.lang.String hello(java.lang.String);descriptor: (Ljava/lang/String;)Ljava/lang/String;flags: ACC_PUBLIC, ACC_ABSTRACT}SourceFile: "FF.java"
同时,我也发现了,这种问题不是个例,例如feign的interface定义,也必须是要使用注解的,可以是springmvc的,也可以使用feign本身的。其原因大概如此。
总结
在移除 Param 注解路上,发现了为什么SpringMVC为什么可以不需要注解,而Mybatis又必须依赖注解,解决问题的路上稍微有点曲折,但是最终还是解决了。 丢失了4分我有些不解
so bad,在我写这个的时候又收获了一个反对票,-6分。
