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 }}
评论