//最近学习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();
}
//完成