public class ResourceClassVisitor extends ClassVisitor implements Opcodes {
public ResourceClassVisitor(ClassVisitor cv) {
super(Opcodes.ASM4, cv);
}
public ResourceClassVisitor(int i, ClassVisitor classVisitor) {
super(i, classVisitor);
}
/**访问类基本信息*/
@Override
public void visit(int version, int access, String name,
String signature, String superName, String[] interfaces) {
this.cv.visit(version, access, name, signature, superName, interfaces);
}
/**访问方法基本信息*/
@Override
public MethodVisitor visitMethod(int access, String name,
String desc, String signature, String[] exceptions) {
MethodVisitor mv = this.cv.visitMethod(access, name, desc,
signature, exceptions);
//假如不是构造方法,我们构建方法的访问对象(MethodVisitor)
if (!name.equals("<init>") && mv != null) {
mv = new ResourceClassVisitor.MyMethodVisitor((MethodVisitor)mv);
}
return (MethodVisitor)mv;
}
/**自定义方法访问对象*/
class MyMethodVisitor extends MethodVisitor implements Opcodes {
public MyMethodVisitor(MethodVisitor mv) {
super(Opcodes.ASM4, mv);
}
/**此方法会在方法执行之前执行*/
@Override
public void visitCode() {
super.visitCode();
this.mv.visitFieldInsn(Opcodes.GETSTATIC, "java/lang/System", "out",
"Ljava/io/PrintStream;");
this.mv.visitLdcInsn("方法开始执行start");
this.mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/io/PrintStream",
"println", "(Ljava/lang/String;)V", false);
}
/**对应方法体本身*/
@Override
public void visitInsn(int opcode) {
//在方法return或异常之前,添加一个end输出
if ((opcode >= Opcodes.IRETURN && opcode <= Opcodes.RETURN) || opcode == Opcodes.ATHROW) {
this.mv.visitFieldInsn(Opcodes.GETSTATIC, "java/lang/System", "out",
"Ljava/io/PrintStream;");
this.mv.visitLdcInsn("方法执行结束end");
this.mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/io/PrintStream",
"println", "(Ljava/lang/String;)V", false);
}
this.mv.visitInsn(opcode);
}
}
}
public class AopTest {
public static void main(String[] args) throws IOException {
//第一步:构建ClassReader对象,读取指定位置的class文件(默认是类路径-classpath)
ClassReader classReader = new ClassReader("com/aop/SayService");
//第二步:构建ClassWriter对象,基于此对象创建新的class文件
//ClassWriter.COMPUTE_FRAMES 表示ASM会自动计算max stacks、max locals和stack map frame的具体内容。
//ClassWriter.COMPUTE_MAXS 表示ASM会自动计算max stacks和max locals,但不会自动计算stack map frames。
ClassWriter classWriter = new ClassWriter(ClassWriter.COMPUTE_FRAMES);//推荐使用COMPUTE_FRAMES
//第三步:构建ClassVisitor对象,此对象用于接收ClassReader对象的数据,并将数据处理后传给ClassWriter对象
ClassVisitor classVisitor = new ResourceClassVisitor(classWriter);
//第四步:基于ClassReader读取class信息,并将数据传递给ClassVisitor对象
//这里的参数ClassReader.SKIP_DEBUG表示跳过一些调试信息等,ASM代码看上去就会更简洁
//这里的参数ClassReader.SKIP_FRAMES表示跳过一些方法中的部分栈帧信息,栈帧手动计算非常复杂,所以交给系统去做吧
//推荐用这两个参数
classReader.accept(classVisitor, ClassReader.SKIP_DEBUG|ClassReader.SKIP_FRAMES);
//第五步:从ClassWriter拿到数据,并将数据写出到一个class文件中
byte[] data = classWriter.toByteArray();
//将字节码写入到磁盘的class文件
File f = new File("target/classes/com/aop/SayService.class");
FileOutputStream fout = new FileOutputStream(f);
fout.write(data);
fout.close();
SayService rs = new SayService();
rs.say("asm");//start,handle(),end
}
}
评论