javassist实现AOP

实际开发中,我们可能碰到需要增强现有的方法,但是手上又没有源码无法修改的情况,可以使用javassist实现类似的AOP功能;

 /**
     * 运行时创建类、修改类
     * @param args
     * @throws NotFoundException
     * @throws CannotCompileException
     * @throws InstantiationException
     * @throws IllegalAccessException
     * @throws IOException
     * @throws InvocationTargetException
     * @throws NoSuchMethodException
     */
    public static void main(String[] args) throws NotFoundException, CannotCompileException, InstantiationException, IllegalAccessException, IOException, InvocationTargetException, NoSuchMethodException {
        /**
         * 创建新类
         */
        createClass();
        /**
         * 修改类
         */
        editClass();
    }

运行时创建新类

/**
     * 运行是创建类
     * @throws CannotCompileException
     * @throws IOException
     * @throws NotFoundException
     * @throws InstantiationException
     * @throws IllegalAccessException
     * @throws NoSuchMethodException
     * @throws InvocationTargetException
     */
    public static void createClass() throws CannotCompileException, IOException, NotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException {
        ClassPool pool = ClassPool.getDefault();
        //运行时新增类Person
        CtClass ctClass = pool.makeClass("com.abc.agent.vo.Person");

        CtField ctField  = new CtField(pool.get("java.lang.String"), "username", ctClass);
        //username属性设置为私有
        ctField.setModifiers(Modifier.PRIVATE);
        //username属性,默认值:hello zhangsan!
        ctClass.addField(ctField, CtField.Initializer.constant("hello zhangsan!"));

        //给Person的username属性,增加get/set方法
        ctClass.addMethod(CtNewMethod.setter("setUsername", ctField));
        ctClass.addMethod(CtNewMethod.getter("getUsername", ctField));

        //增加无参构造函数
        CtConstructor constructor = new CtConstructor(new CtClass[]{}, ctClass);
        // $0=this / $1,$2,$3... 代表方法参数
//        String string = UUID.randomUUID().toString();
        constructor.setBody("{username = \"sdfwer234234\";}");
        //constructor.setBody("{$0.username=$1;}");
        ctClass.addConstructor(constructor);

        //自定义方法
        CtMethod ctMethod = new CtMethod(CtClass.voidType, "show", new CtClass[]{}, ctClass);
        ctClass.setModifiers(Modifier.PUBLIC);
        ctMethod.setBody("{System.out.println(username);}");
        ctClass.addMethod(ctMethod);
        //输出Person.class文件
        ctClass.writeFile("T:/");

        /**
         * 反射调用运行时动态生成的类
         */
        Object person = ctClass.toClass().newInstance();
        Method show = person.getClass().getMethod("show");
        show.invoke(person);

        //使用完成,清理掉内存
        ctClass.detach();
    }

运行时修改现有类

/**
     * 运行时,修改现有类
     * @throws CannotCompileException
     * @throws NotFoundException
     * @throws InstantiationException
     * @throws IllegalAccessException
     * @throws InvocationTargetException
     * @throws NoSuchMethodException
     * @throws IOException
     */
    private static void editClass() throws CannotCompileException, NotFoundException, InstantiationException, IllegalAccessException, InvocationTargetException, NoSuchMethodException, IOException {
        ClassPool pool = ClassPool.getDefault();
        CtClass ctClass = pool.get("com.abc.agent.Class1");

        CtMethod ctMethod = ctClass.getDeclaredMethod("sayHi");
        //AOP, sayHi方法调用前,新增一行代码;
        ctMethod.insertBefore("{ System.out.println(\"AAAAA\"); }");
        //AOP, sayHi方法调用后,新增一行代码;
        ctMethod.insertAfter("{ System.out.println(\"BBBBBB\"); }");

        Object newInstance = ctClass.toClass().newInstance();
        Method sayHi = newInstance.getClass().getMethod("sayHi");
        sayHi.invoke(newInstance);

        ctClass.writeFile(".");
        //使用完成,清理掉内存
        ctClass.detach();
    }
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容