相当于在代码里面写AOP,因此要想实现 Aop 的关键是,如何将我们的代码安插到被调用方法的相应位置。
首先加入asm的依赖
org.ow2.asm
asm-all
5.1
package com.agent.my5;
public class Operation
{
public void oper()
{
System.out.println("***********这里是执行的逻辑**********");
}
}
package com.agent.my5;
public class Log
{
public static void startLog()
{
System.out.println("start log ...");
}
public static void endLog()
{
System.out.println("end log ...");
}
}
示例代码如下:
package com.agent.my5;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassWriter;
/**
* 使用ASM实现AOP功能
*/
public class ASMAop
{
public static void main(String[] args)throws Exception
{
ClassReader cr = new ClassReader("com.agent.my5.Operation");
ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS);
cr.accept(new LogClassVisitor(cw), ClassReader.SKIP_DEBUG);
Class> clazz = new MyClassLoader().defineClassForName("com.agent.my5.Operation", cw.toByteArray());
clazz.getMethods()[0].invoke(clazz.newInstance());
}
}
class MyClassLoader extends ClassLoader {
public MyClassLoader() {
super(Thread.currentThread().getContextClassLoader());
}
public Class> defineClassForName(String name, byte[] data) {
return this.defineClass(name, data, 0, data.length);
}
}
package com.agent.my5;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
public class LogClassVisitor extends ClassVisitor
{
public LogClassVisitor(ClassVisitor cv)
{
super(Opcodes.ASM5, cv);
}
public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions)
{
if("oper".equals(name))
{
return new LogMethodVisitor(super.visitMethod(access, name, desc, signature, exceptions));
}
return super.visitMethod(access, name, desc, signature, exceptions);
}
}
package com.agent.my5;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
public class LogMethodVisitor extends MethodVisitor
{
public LogMethodVisitor(MethodVisitor mv)
{
super(Opcodes.ASM5, mv);
}
public void visitCode() {
/**
* 方法执行之前植入代码
*/
super.visitMethodInsn(Opcodes.INVOKESTATIC, "com/agent/my5/Log", "startLog", "()V", false);
super.visitCode();
}
public void visitInsn(int opcode)
{
if(opcode == Opcodes.RETURN)
{
/**
* 方法return之前,植入代码
*/
super.visitMethodInsn(Opcodes.INVOKESTATIC, "com/agent/my5/Log", "endLog", "()V", false);
}
super.visitInsn(opcode);
}
}
start log ...
***********这里是执行的逻辑**********
end log ...