美文网首页
深入字节码 -- 使用 ASM 实现 AOP

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

作者: 小鹏166 | 来源:发表于2018-11-22 18:14 被阅读0次

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

        }

    }

    相关文章

      网友评论

          本文标题:深入字节码 -- 使用 ASM 实现 AOP

          本文链接:https://www.haomeiwen.com/subject/uecrqqtx.html