ASM函数监听实现(二)之打印注入函数的参数值
上一篇博客中实现了asm简单的对类中方法添加监听。
http://xkorey.iteye.com/admin/blogs/1551897
监听只是一个简单的切入并未对所切入方法的值做任何处理。
简单的打印出了
it's begin helloWorld.... it's end
这次也做一点小改动,将改为
start value:helloend value:hello world
将实现:监听函数的传入值。
首先将测试类 helloWorld 改造为:
public class helloWorld {public void sayHello(String parm){parm+=" world";}}
其次改造 asmAopMethodAdapter 对方法做修改的类,
public class asmAopMethodAdapter extends MethodAdapter implements Opcodes{private final static int EXCEPTION_STACK = 2 + 1;//max_stack至少需要能够容纳2个常量地址(监控方法使用)和1个exception地址private Label try_catch_start,try_catch_end;private String startInfo,endInfo; public asmAopMethodAdapter(MethodVisitor mv,String start,String end) { super(mv); try_catch_start = new Label(); try_catch_end = new Label(); startInfo = start; endInfo = end; } public void visitCode() { mv.visitCode(); mv.visitLabel(try_catch_start); mv.visitVarInsn(ALOAD, 0); mv.visitVarInsn(ALOAD, 1); // mv.visitLdcInsn(startInfo);//asmAopInvoker 这里写类的路径例如:com.asm.asmAopInvoker 应写成 com/asm/asmAopInvoker mv.visitMethodInsn(INVOKESTATIC, "asmAopInvoker", "methodStart", "(Ljava/lang/String;)V"); } public void visitInsn(int opcode){ if(opcode >= IRETURN && opcode <= RETURN){ mv.visitVarInsn(ALOAD, 0); mv.visitVarInsn(ALOAD, 1);//mv.visitLdcInsn(endInfo);//asmAopInvoker 这里写类的路径例如:com.asm.asmAopInvoker 应写成 com/asm/asmAopInvoker mv.visitMethodInsn(INVOKESTATIC, "asmAopInvoker", "methodEnd", "(Ljava/lang/String;)V"); } mv.visitInsn(opcode); } public void visitEnd() { mv.visitLabel(try_catch_end); mv.visitTryCatchBlock(try_catch_start, try_catch_end, try_catch_end, null); //mv.visitLdcInsn(endInfo);//asmAopInvoker 这里写类的路径例如:com.asm.asmAopInvoker 应写成 com/asm/asmAopInvoker //mv.visitMethodInsn(INVOKESTATIC, "asmAopInvoker", "methodEnd", "(Ljava/lang/String;)V"); mv.visitInsn(Opcodes.ATHROW); mv.visitEnd(); } public void visitMaxs(int maxStack,int maxLocals){//保证max stack足够大 mv.visitMaxs(Math.max(EXCEPTION_STACK,maxStack), maxLocals); }}
其中改变的部分是
将
// 个人理解:是将一个Object写入到class中mv.visitLdcInsn(endInfo);
改为
// 个人理解:访问方法内的第一个参数mv.visitVarInsn(ALOAD, 0);// 个人理解:获取这个参数的值mv.visitVarInsn(ALOAD, 1);
这次运行环境依旧是jdk1.6,asm 3.3.1
其中的类已打包。