当前位置: 代码迷 >> Web前端 >> AOP:ASM直接替类方法添加前拦截执行(区别于无损方式)
  详细解决方案

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

热度:149   发布时间:2012-11-23 00:03:43.0
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();

? }

//完成

  相关解决方案