AOP:ASM直接为类方法添加前拦截执行(区别于无损方式)

//最近学习ASM的一点总结
//首先这种方式会更新原来的class文件,总体感觉不是很好,不过其思路很是可以借鉴!!

//1、为AccountAsm类的operation方法添加 安全检查方法 ,在执行operation前执行 SecurityChecker.checkSecurity

//首先 建立SecurityChecker 和 AccountAsm 类

--------------------------------------------------------------------------------
package com.security;

public class SecurityChecker {
 public static void checkSecurity() {
   System.out.println("SecurityChecker.checkSecurity ...");
   //TODO real security check
  }
}
--------------------------------------------------------------------------------
package com.aop;
public class AccountAsm {
 public void operation()
 {
   System.out.println("operation...");

   //TODO real operation
 }
}
--------------------------------------------------------------------------------

//2、然后 实现一个 methodAdapter 类,用于 修改方法

package com.aop;

import org.objectweb.asm.MethodAdapter;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;

public class AddSecurityCheckMethodAdapter extends MethodAdapter {

 

 public AddSecurityCheckMethodAdapter(MethodVisitor mv) {
   super(mv);
  }
           //com/security/SecurityChecker 此点很总要,不能写成com.security.SecurityChecker
  public void visitCode() {
   visitMethodInsn(Opcodes.INVOKESTATIC, "com/security/SecurityChecker",
   "checkSecurity", "()V");
  }


}

}


//3、再然后实现一个ClassAdapter 用于判断 何时修改AccountAsm 类方法

package com.aop;

import org.objectweb.asm.ClassAdapter;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.MethodVisitor;

public class AddSecurityCheckClassAdapter extends ClassAdapter
{

 public String enhancedSuperName;
 public AddSecurityCheckClassAdapter(ClassVisitor cv) {
        //Responsechain 的下一个 ClassVisitor,这里我们将传入 ClassWriter,
        // 负责改写后代码的输出
        super(cv);
    }

    // 重写 visitMethod,访问到 "operation" 方法时,
    // 给出自定义 MethodVisitor,实际改写方法内容
    public MethodVisitor visitMethod(final int access, final String name,
        final String desc, final String signature, final String[] exceptions) {
        MethodVisitor mv = cv.visitMethod(access, name, desc, signature,exceptions);
        MethodVisitor wrappedMv = mv;
        if (mv != null) {
            // 对于 "operation" 方法
            if (name.equals("operation")) {
                // 使用自定义 MethodVisitor,实际改写方法内容
                wrappedMv = new AddSecurityCheckMethodAdapter(mv);
            }  }
        return wrappedMv;
    }

}

//4、读取原来的AccountAsm.class文件,并为operation方法前添加SecurityChecker.checkSecurity(),然后 生产新的class文件

public static void main(String[] args) throws Exception {

  ClassReader cr = new ClassReader("com.aop.AccountAsm");
   ClassWriter cw = new ClassWriter(true);
   ClassAdapter classAdapter = new AddSecurityCheckClassAdapter(cw);
   cr.accept(classAdapter, true);
   byte[] data = cw.toByteArray();

   String classPath = (
        AccountAsm.class.getResource("/").toString() +
        AccountAsm.class.getCanonicalName().replace(".", File.separator)+
        ".class"
        ).substring(6)
        ;

   File file = new File(classPath);
   FileOutputStream fout = new FileOutputStream(file);
   fout.write(data);
   fout.close();

  }

//完成

你可能感兴趣的:(AOP,ASM)