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

AOP:ASM直接替类方法添加前拦截执行-无损方法

2012-12-28 
AOP:ASM直接为类方法添加前拦截执行--无损方法//所谓无损即 在不改变原有类文件的情况下,为指定方法 添加

AOP:ASM直接为类方法添加前拦截执行--无损方法

//所谓无损即 在不改变原有类文件的情况下,为指定方法 添加前拦截,总体实现与前一个例子差不多,但是不需要生产新的类文件。

//思路:
//改变 Class Description, 将其命名为 Account$EnhancedByASM,将其父类指定为 AccountASM。
//改变构造函数,将其中对父类构造函数的调用转换为对 AccountASM构造函数的调用。

//著名的 Hibernate 和 Spring 框架,就是使用这种技术实现了 AOP 的“无损注入”。

//1、首先实现一个 实现一个 methodAdapter 类,用于 修改方法,已经存在AddSecurityCheckMethodAdapter? 上例子

//2、再实现一个methodAdapter 类,用于构建新类Account$EnhancedByASM,将其父类指定为 AccountASM

package com.aop;

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

public class ChangeToChildConstructorMethodAdapter extends MethodAdapter {
?private String superClassName;

? public ChangeToChildConstructorMethodAdapter(MethodVisitor mv,
?? String superClassName) {
?? super(mv);
?? this.superClassName = superClassName;
? }

? public void visitMethodInsn(int opcode, String owner, String name,
?? String desc) {
?? // 调用父类的构造函数时
?? if (opcode == Opcodes.INVOKESPECIAL && name.equals("<init>")) {
??? owner = superClassName;
?? }
?? super.visitMethodInsn(opcode, owner, name, desc);// 改写父类为 superClassName
? }

}

//3、完善AddSecurityCheckClassAdapter 类,控制生产新的类和修改类方法

public class AddSecurityCheckClassAdapter extends ClassAdapter
{

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


?public void visit(final int version, final int access, final String name,
??? final String signature, final String superName,
??? final String[] interfaces) {
?? String enhancedName = name + "$EnhancedByASM";? // 改变类命名
?? enhancedSuperName = name; // 改变父类,这里是”Account”
?? super.visit(version, access, enhancedName, signature,
?? enhancedSuperName, interfaces);
? }


??? // 重写 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);
??????????? }
??????????? else if (name.equals("<init>")) {
?? ??? wrappedMv = new ChangeToChildConstructorMethodAdapter(mv,
?? ????? enhancedSuperName);
?? ??? }

??????? }
??????? return wrappedMv;
??? }

}

//4、新建Generator类,用户获取新生产的类对象

public class Generator {


?private static AccountGeneratorClassLoader classLoader =
??????? new AccountGeneratorClassLoader();

??? private static Class secureAccountClass;

??? public static AccountAsm generateSecureAccount() throws Exception {
??????? if (null == secureAccountClass) {
??????? ? 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();
??????????? secureAccountClass = classLoader.defineClassFromClassFile(
?????????????? "com.aop.AccountAsm$EnhancedByASM",data);
??????? }
??????? return (AccountAsm) secureAccountClass.newInstance();
??? }

??? private static class AccountGeneratorClassLoader extends ClassLoader {
??????? public Class defineClassFromClassFile(String className,
??????????? byte[] classFile) throws ClassFormatError {
??????????? return defineClass(className, classFile, 0,
???????? classFile.length);
??????? }
??? }
}

//5、调用
AccountAsm a=? Generator.generateSecureAccount();
a.operation();

ClassWriter(int flags)
          Constructs a new ClassWriter object.

只有这两个吧? 2 楼 baihongsheng 2012-03-14   import org.objectweb.asm.ClassWriter
asm-2.0.RC1.jar 3 楼 glmylove 2012-03-16   baihongsheng 写道import org.objectweb.asm.ClassWriter
asm-2.0.RC1.jar


我用的3.1的,看来方法已经改变了吧

热点排行