上一篇博客中实现了asm简单的对类中方法添加监听。
[url]http://xkorey.iteye.com/admin/blogs/1551897[/url]
监听只是一个简单的切入并未对所切入方法的值做任何处理。
简单的打印出了
这次也做一点小改动,将改为
将实现:监听函数的传入值。
首先将测试类 helloWorld 改造为:
其次改造 asmAopMethodAdapter 对方法做修改的类,
其中改变的部分是
将
改为
这次运行环境依旧是jdk1.6,asm 3.3.1
其中的类已打包。
[url]http://xkorey.iteye.com/admin/blogs/1551897[/url]
监听只是一个简单的切入并未对所切入方法的值做任何处理。
简单的打印出了
it's begin
helloWorld....
it's end
这次也做一点小改动,将改为
start value:hello
end 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
其中的类已打包。