//所谓无损即 在不改变原有类文件的情况下,为指定方法 添加前拦截,总体实现与前一个例子差不多,但是不需要生产新的类文件。
//思路:
//改变 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();