jdk中的proxy必须基于接口,封装了asm的cglib没有这种限制。
关于ASM
ASM是一个Java字节码操纵框架,它能被用来动态生成类或者增强既有类的功能。ASM可以直接产生二进制class文件,也可以在类被加载入Java虚拟机之前动态改变类行为。
AOP一种较好的实现方式就是修改class文件织入逻辑,cglib正是通过ASM实现动态代理。 若想直接在字节码中增加内容,要对class文件结构和Java字节码有一定的了解,如方法和字段的描述符。(若要用复杂的逻辑需要ASM-Bytecode工具,会直接生成ASM代码)
| 标示字符 | 含义 |
|---|---|
| B | 基本类型byte |
| C | 基本类型char |
| I | 基本类型int |
| J | 基本类型long |
| Z | 基本类型boolean |
| V | 特殊类型void |
| L | 对象类型,如Ljava/lang/String |
idea可以直接查看每个类的字节码。

demo
demo用ASM实现删除类中的方法、改变类中的方法、加入aop
原始的类:
public class SrcClass {
//要删除的方法
public void change1() {
System.out.println("i am change-one!");
}
public void change2() {
System.out.println("i am change-two");
}
}
方法中要增加的逻辑
System.out.println("i am new");
要加载的aop方法
public class AopContent {
public static void content(){
System.out.println("i am aop");
}
}
最后相当于要把SrcClass变成
public class SrcClass {
public void change2() {
System.out.println("i am new");
System.out.println("i am aop");
System.out.println("i am change-two");
}
}
安插 Aop、删除方法和修改方法的ASM代码
public class AopMethodVisitor extends MethodVisitor implements Opcodes {
public AopMethodVisitor(int i, MethodVisitor methodVisitor) {
super(i, methodVisitor);
}
@Override
public void visitCode() {
super.visitCode();
this.visitMethodInsn(INVOKESTATIC, "cn/qs/asm/AopContent", "content", "()V", false);
}
}
class DemoVisitor extends ClassVisitor implements Opcodes {
public DemoVisitor(int api, ClassVisitor cv) {
super(api, cv);
}
@Override
public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) {
if (name.equals("change1")) {
return null;
}
MethodVisitor mv = super.visitMethod(access, name, desc, signature, exceptions);
if (name.equals("change2")) {
mv.visitFieldInsn(GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;");
mv.visitLdcInsn("i am new");
mv.visitMethodInsn(INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/String;)V",false);
return new AopMethodVisitor(this.api, mv);
}
return mv;
}
}
ASM改写Java类
public class App extends ClassLoader implements Opcodes {
public static void main(String[] args) throws IOException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, SecurityException, InstantiationException, InvocationTargetException, NoSuchMethodException {
ClassReader cr=new ClassReader(SrcClass.class.getName());
ClassWriter cw=new ClassWriter(ClassWriter.COMPUTE_MAXS);
DemoVisitor myv=new DemoVisitor(Opcodes.ASM4,cw);
cr.accept(myv, 0);
byte[] code=cw.toByteArray();
//自定义加载器
App loader=new App();
Class<?> appClass=loader.defineClass(null, code, 0,code.length);
appClass.getMethods()[0].invoke(appClass.newInstance(), new Object[]{});
Method[] methodArray = appClass.getMethods();
}
最后输出结果:
i am new
i am aop
i am change-two
同时查看methodArray中已经没有方法change1
