使用ASM4.0实现AOP的功能,监控每个方法的执行时间
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 MethodVisitor {
public AsmMethodVisit(MethodVisitor mv) {
super(Opcodes.ASM4, mv);
&nb
补充:软件开发 , Java ,