首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > 编程 >

ASM函数监听兑现(三)拦截注入函数的参数值 (函数执行前)

2012-12-28 
ASM函数监听实现(三)拦截注入函数的参数值 (函数执行前)上一篇ASM中打印出了被注入函数参数的传入值,http:

ASM函数监听实现(三)拦截注入函数的参数值 (函数执行前)
上一篇ASM中打印出了被注入函数参数的传入值,http://xkorey.iteye.com/admin/blogs/1667944

现在将要实现对参数传入值的拦截,不符合判断规则的传入值,将会被直接返回。
实现如下效果:

// 打印出参数传入值start value:error// 发现值等于 error 时直接返回error,program will exit.//属性值并未被更改default// 打印出传入值start value:changeend value:change// 属性值被更改change


被拦截的方法是helloWorld中的sayHello
public class helloWorld {public String va="default";public void sayHello(String param){va=param;}}


测试代码

asmAopGenerator aag = new asmAopGenerator();helloWorld hw = (helloWorld) aag.proxy(helloWorld.class, "sayHello", "it's begin", "it's end");                // 传入值是error时直接返回 va的值没改变hw.sayHello("error");                // 打印出defaultSystem.out.println(hw.va);// va的值被改变                hw.sayHello("change");                // 打印出 va的值为 changeSystem.out.println(hw.va);


注入到被拦截类的对象:

public class asmAopInvoker {public static int methodEnd(String evtID){System.out.println("end value:"+evtID);return 0;}public static int methodStart(String evtID){System.out.println("start value:"+evtID);if(evtID.equals("error")){System.out.println("error,program will exit.");return 1;}return 0;}}


方法拦截对象就是上一篇中的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);                 // 加入if标签 Label if_Lable = new Label();                 // 获得函数 methodStart 的返回值 mv.visitVarInsn(ALOAD, 1); // 调用 methodStart函数                 // (Ljava/lang/String;)I 意为:接受一个类型为string参数                 // 返回值为int的函数                  mv.visitMethodInsn(INVOKESTATIC, "asmAop/asmAopInvoker", "methodStart", "(Ljava/lang/String;)I"); // 访问if 标签                  // 疑惑 asm4-guide 中说明 IFEQ的意思是:jump if i  == 0。但我在asm 3.3.1中貌似IFEQ是 jump if i==1                  mv.visitJumpInsn(IFEQ, if_Lable); // 写入 return                 mv.visitInsn(RETURN); // 结束if标签                 mv.visitLabel(if_Lable);  }   public void visitInsn(int opcode){ if(opcode >= IRETURN && opcode <= RETURN){ mv.visitCode(); mv.visitVarInsn(ALOAD, 0); mv.visitVarInsn(ALOAD, 1); mv.visitMethodInsn(INVOKESTATIC, "asmAop/asmAopInvoker", "methodEnd", "(Ljava/lang/String;)I"); } mv.visitInsn(opcode); } public void visitEnd() { mv.visitLabel(try_catch_end); mv.visitTryCatchBlock(try_catch_start, try_catch_end, try_catch_end, null); mv.visitInsn(Opcodes.ATHROW); mv.visitEnd(); }  public void visitMaxs(int maxStack,int maxLocals){//保证max stack足够大 mv.visitMaxs(Math.max(EXCEPTION_STACK,maxStack), maxLocals); }}




所涉及类以打包。

代码运行环境 asm 3.3.1 jdk 1.6.

热点排行