https://www.oschina.net/code/snippet_1166271_24995
使用ASM改写字节码实现Aop,是最快的Aop实现方式。下面是一个简单的示例,共学习使用。
文章 http://my.oschina.net/u/1166271/blog/162796 详细介绍了如何深入字节码实现这一功能。
下面的代码片段是使用 ASM 4.0 版本进行的字节码操作,并且下面所有代码为 Blog的配套代码。
源码与演示:源码出处
1. [代码]目标类
publicclassTestBean {
publicvoidhalloAop() {
System.out.println("Hello Aop");
}
}
2. [代码]Aop拦截器处理程序
publicclassAopInterceptor {
publicstaticvoidbeforeInvoke() {
System.out.println("before");
};
publicstaticvoidafterInvoke() {
System.out.println("after");
};
}
3. [代码]生成字节码并负责转换为Class类型的类装载器
classAopClassLoader extendsClassLoader implementsOpcodes {
publicAopClassLoader(ClassLoader parent) {
super(parent);
}
publicClass<?> loadClass(String name) throwsClassNotFoundException {
if(!name.contains("TestBean_Tmp"))
returnsuper.loadClass(name);
try{
ClassWriter cw = newClassWriter(0);
//
InputStream is = Thread.currentThread().getContextClassLoader().getResourceAsStream("org/more/test/asm/TestBean.class");
ClassReader reader = newClassReader(is);
reader.accept(newAopClassAdapter(ASM4, cw), ClassReader.SKIP_DEBUG);
//
byte[] code = cw.toByteArray();
// FileOutputStream fos = new FileOutputStream("c:\\TestBean_Tmp.class");
// fos.write(code);
// fos.flush();
// fos.close();
returnthis.defineClass(name, code, 0, code.length);
} catch(Throwable e) {
e.printStackTrace();
thrownewClassNotFoundException();
}
}
}
4. [代码]ASM 改写字节码的完整程序 跳至 [1] [2] [3] [4] [全屏预览]
classAopClassAdapter extendsClassVisitor implementsOpcodes {
publicAopClassAdapter(intapi, ClassVisitor cv) {
super(api, cv);
}
publicvoidvisit(intversion, intaccess, String name, String signature, String superName, String[] interfaces) {
//更改类名,并使新类继承原有的类。
super.visit(version, access, name + "_Tmp", signature, name, interfaces);
{
MethodVisitor mv = super.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null);
mv.visitCode();
mv.visitVarInsn(ALOAD, 0);
mv.visitMethodInsn(INVOKESPECIAL, name, "<init>", "()V");
mv.visitInsn(RETURN);
mv.visitMaxs(1, 1);
mv.visitEnd();
}
}
publicMethodVisitor visitMethod(intaccess, String name, String desc, String signature, String[] exceptions) {
if("<init>".equals(name))
returnnull;
if(!name.equals("halloAop"))
returnnull;
//
MethodVisitor mv = super.visitMethod(access, name, desc, signature, exceptions);
returnnewAopMethod(this.api, mv);
}
}
classAopMethod extendsMethodVisitor implementsOpcodes {
publicAopMethod(intapi, MethodVisitor mv) {
super(api, mv);
}
publicvoidvisitCode() {
super.visitCode();
this.visitMethodInsn(INVOKESTATIC, "org/more/test/asm/AopInterceptor", "beforeInvoke", "()V");
}
publicvoidvisitInsn(intopcode) {
if(opcode == RETURN) {
mv.visitMethodInsn(INVOKESTATIC, "org/more/test/asm/AopInterceptor", "afterInvoke", "()V");
}
super.visitInsn(opcode);
}
}
网友评论