五、cglib及asm
spring的aop功能生成的代理类使用的cglib,cglib的底层实现是asm。
我们先分析下cglib,编写cglib代理时,最主要的就是编写Callback接口实现类,我们时常编写的实现类实现接口MethodInterceptor,该接口也是继承了Callback接口。实现了MehthodInterceptor接口之后,需要实现invoke方法。这样就可以使用cglib代理类了。
我认为如果我们真的要生成一个类,可能只会用到ClassWriter、MethodVisitor,ClassReader、ClassVisitor可能用不到。用ClassReader结合ClassWriter的时候很坑,总会生成2个方法。用ClassWriter可能会好点,但是属性、字段、方法都要自己去生成,工作量会大点。
用ClassReader结合ClassWriter的时候,类的方法、属性都带过来了,可能要写个adapter,对reader的事件进行过滤,比如访问到某个方法的时候,就把这个方法移除掉。
对应asm呢?如果我们要修改一个类的方法,那么就首先用到ClassWriter visit访问这个类,然后用MethodVisitor去改造这个方法。那么如何简单去用asm代码去改造一个类呢?
比如我们有一个已经编写好的类Programmer:
我们需要改造成如下,修改它打印的内容:
那么我们最简单的办法是什么呢? 我认为一定不是去直接编写ams代码,而是先把这个改造后的类先用Java代码编写出来,然后进行javap –c去分析这个类,如下:
然后再根据这个反编译的结果去用asm代码编写我们的类,
可以看到,编写的代码跟我们javap指令的结构很相似。这样编写的难度及代码错误率会减少。
还有一种更简单的方法是, 也是自己先编写好类, 然后运行org.objectweb.asm.util. ASMifier, 把自己的全路径下的类作为参数传递过去就OK了。
自己编写asm代码的时候,有很多坑,比如“Ljava/lang/String;”后面少了个分号就不行了。