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