AOP与代码生成技术

Javassist 实现AOP、动态创建代码

2019-09-29  本文已影响0人  ImWiki

Javassist是基于ASM,提供了更高级的API,执行效率比ASM差一些,但无需掌握字节码指令的知识,对使用者要求较低,多数的Android热修复框架都是基于Javassist实现。

代表框架:InstantRun、HotFix。

动态代理教程

添加依赖

implementation 'org.javassist:javassist:3.25.0-GA'

代码

public class JavassistTest implements MethodHandler {
    public static void main(String[] args) throws IllegalAccessException, InstantiationException {
        User user = new JavassistTest().getProxy(User.class);
        user.setId(1);
        System.out.println("Id: "+user.getId());
    }
    private <T> T getProxy(Class<T> clazz) throws InstantiationException, IllegalAccessException {
        ProxyFactory proxyFactory = new ProxyFactory();
        proxyFactory.setSuperclass(clazz);
        Class<?> proxyClass = proxyFactory.createClass();
        T result = (T)proxyClass.newInstance();
        ((ProxyObject)result).setHandler(this);
        return result;
    }
    @Override
    public Object invoke(Object obj, Method thisMethod, Method method, Object[] args) throws Throwable {
        System.out.println("执行开始:" + method);
        Object result = method.invoke(obj, args);
        System.out.println("执行结束:" + method);
        return result;
    }
    public static class User {
        private int id;
        public int getId() {return id;}
        public void setId(int id) {this.id = id;}
    }
}

结果

执行开始:public final void com.thejoyrun.aptpreferences.JavassistTest$User_$$_jvst617_0._d8setId(int)
执行结束:public final void com.thejoyrun.aptpreferences.JavassistTest$User_$$_jvst617_0._d8setId(int)
执行开始:public final int com.thejoyrun.aptpreferences.JavassistTest$User_$$_jvst617_0._d4getId()
执行结束:public final int com.thejoyrun.aptpreferences.JavassistTest$User_$$_jvst617_0._d4getId()
Id: 1

动态创建代码

public class JavassistDefineClassTest {
    public static void main(String[] args) throws CannotCompileException, InstantiationException, IllegalAccessException, InvocationTargetException, NoSuchMethodException {
        // 创建类池,true 表示使用默认路径
        ClassPool classPool = new ClassPool(true);
        CtClass ctClass = classPool.makeClass("User");
        ctClass.addField(CtField.make("private int id;", ctClass));
        ctClass.addMethod(CtNewMethod.make("public void setId(int id) {this.id = id;}", ctClass));
        ctClass.addMethod(CtNewMethod.make("public int getId() {return id;}", ctClass));
        Class testClass = ctClass.toClass();
        Object object = testClass.newInstance();
        Method setMethod = testClass.getMethod("setId", int.class);
        Method getMethod = testClass.getMethod("getId");

        setMethod.invoke(object, 101);
        System.out.println("userId: "+getMethod.invoke(object));
    }
}

结果

userId: 101
上一篇下一篇

猜你喜欢

热点阅读