使用ASM4.0实现AOP的功能,监控每个方法的执行时间(一)

2014-11-24 09:09:56 · 作者: · 浏览: 2

AOP的更通用的做法是对原始类动态生成子类,调用子类的方法覆盖父类,来实现AOP的功能。著名的 Hibernate 和 Spring 框架,就是使用这种技术实现了 AOP 的“无损注入”。

下面我们就通过一个示例来对方法Foo.execute调用时动态注入方法执行前后的时间统计来统计方法的执行时间

[java]
import java.io.FileOutputStream;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;

public class AsmAopExample extends ClassLoader implements Opcodes{

public static class Foo {
public static void execute() {
System.out.println("test changed method name");
try {
Thread.sleep(10);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}

public static class Monitor{

static long start = 0;

public static void start(){
start = System.currentTimeMillis();
}
public static void end(){
long end = System.currentTimeMillis();
System.out.println("execute method use time :" + (end - start));
}
}

public static void main(String[] args) throws IOException, IllegalArgumentException, SecurityException, IllegalAccessException, InvocationTargetException {

ClassReader cr = new ClassReader(Foo.class.getName());
ClassWriter cw = new ClassWriter(cr, ClassWriter.COMPUTE_MAXS);
ClassVisitor cv = new MethodChangeClassAdapter(cw);
cr.accept(cv, Opcodes.ASM4);

// gets the bytecode of the Example class, and loads it dynamically

byte[] code = cw.toByteArray();


AsmAopExample loader = new AsmAopExample();
Class< > exampleClass = loader.defineClass(Foo.class.getName(), code, 0, code.length);

for(Method method: exampleClass.getMethods()){
System.out.println(method);
}

exampleClass.getMethods()[0].invoke(null, null); // 用execute,修改方法 容


// gets the bytecode of the Example class, and loads it dynamically

FileOutputStream fos = new FileOutputStream("e:\\logs\\Example.class");
fos.write(code);
fos.close();
}

static class MethodChangeClassAdapter extends ClassVisitor implements Opcodes {

public MethodChangeClassAdapter(final ClassVisitor cv) {
super(Opcodes.ASM4, cv);
}

@Override
public MethodVisitor visitMethod(
int access,
String name,
String desc,
String signature,
String[] exceptions)
{
if("execute".equals(name)) //此处的execute即为需要修改的方法 ,修改方法 容
{
MethodVisitor mv = cv.visitMethod(access, name, desc, signature, exceptions);//先得到原始的方法
MethodVisitor newMethod = null;
newMethod = new AsmMethodVisit(mv); //访问需要修改的方法
return newMethod;
}

return null;
}


}

static class AsmMethodVisit extends Metho