深入字节码 -- 使用 ASM 实现 AOP

2018-11-22  本文已影响0人  小鹏166

https://www.oschina.net/code/snippet_1166271_24995

使用ASM改写字节码实现Aop,是最快的Aop实现方式。下面是一个简单的示例,共学习使用。

文章  http://my.oschina.net/u/1166271/blog/162796  详细介绍了如何深入字节码实现这一功能。

下面的代码片段是使用 ASM 4.0 版本进行的字节码操作,并且下面所有代码为 Blog的配套代码。

标签: Hasor ASM

源码与演示:源码出处

代码片段(4)[全屏查看所有代码]

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);

    }

}

上一篇下一篇

猜你喜欢

热点阅读