这里会带有 10 种 Java、Android 的 AOP 教程
- APT
- AspectJ
- Javassist
- CGLIB
- ByteBuddy
- JDK 动态代理
- ASM
- ASMDEX
- DexMaker
- Xposed
面向切面编程(Aspect-Oriented Programming),是 Java 开发中常见的编程方式,很多著名的开源框架都是基于 AOP 思想实现,比如 Spring、Retrofit、Mybatis 等,实现 AOP 的方式有很多种,主要分为三类:静态编译
、编译期注入代码
、动态编译
,前两者都是在生成 jar、dex 包之前就完成代码处理,动态编译是在运行时实现,比如补丁就是动态编译实现。
.java.class.dex运行时
分类我在这里总结了 10 种 AOP 的方式
名称说明支持APT静态编译Java、AndroidAspectJ使用专门的编译器,在编译期插入代码Java、AndroidJavassist动态编译与动态生成字节码Java、AndroidCGLIB动态编译与动态生成字节码JavaByteBuddy动态编译与动态生成字节码Java、AndroidJDK 动态代理动态代理Java、AndroidASM动态编译与动态生成字节码Java、AndroidASMDEX动态编译与动态生成字节码AndroidDexMaker动态编译与动态生成字节码AndroidXposed需要 root 权限,在运行时插入字节码Android APT(Annotation Processing Tool)APT 技术 Java 应用并不是特别广泛,但是在 Android 中是主要实现 AOP 的方式之一,通过注解实现在编译期间生成代码,执行效率高。
代表框架:ButterKnife、GRouter、AptPreferences
教程Android APT(编译时代码生成)最佳实践
AspectJ使用 AspectJ 编译器(ajc),在编译时期,在关键的的地方插入部分代码,处理相关逻辑,比如可以用于打印方法执行的效率,权限检查等,Spring 就使用了 AspectJ。在 Android 上的应用主要是做性能监控、基于注解的数据埋点等。
代表框架:Hugo、Spring
教程利用 AspectJ 实现 Android 基于注解的无侵入埋点
TODO:所有带有注解的方法都通过经过一个拦截器,可以在拦截器实现打印信息,做埋点等,参考 Hugo,但是让用户自行试行,提供默认的拦截器。
CGLIBCGLIB 是一个强大的,高性能,高质量的 Code 生成类库 ,是基于 ASM 封装,大名鼎鼎的 Hibernate 就是基于 CGLIB 实现,CGLIB 是一个应用非常广泛的 AOP 框架。
代表框架:Hibernate
+--- cglib:cglib:3.3.0| \--- org.ow2.asm:asm:7.1
教程
添加依赖
dependencies { implementation 'cglib:cglib:3.3.0'}
代码
public class CglibTest implements MethodInterceptor { public static void main(String[] args) { User user = (User) new CglibTest().getProxy(User.class); user.setId(1); user.getId(); } public Enhancer enhancer = new Enhancer(); private Object getProxy(Class clazz) { enhancer.setSuperclass(clazz); enhancer.setCallback(this); return enhancer.create(); } @Override public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable { System.out.println("执行开始:" + method); Object result = proxy.invokeSuper(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 void com.thejoyrun.aptpreferences.CglibTest$User.setId(int)执行结束:public void com.thejoyrun.aptpreferences.CglibTest$User.setId(int)执行开始:public int com.thejoyrun.aptpreferences.CglibTest$User.getId()执行结束:public int com.thejoyrun.aptpreferences.CglibTest$User.getId()
ByteBuddy
Byte Buddy 是一个运行时动态生成字节码的库,它是依赖 Java 虚拟机,由于 Android 的字节码和 Java 不同,也提供了 Android 的支持包,大名鼎鼎的测试框架 Mockito 就是基于 ByteBuddy 实现,Mockito3 也正式支持在 Android 运行时环境使用,但是包大小为 3.3MB,建议只在 debug 环境下使用。
api 'net.bytebuddy:byte-buddy:1.10.1'api 'net.bytebuddy:byte-buddy-android:1.10.1'
代表框架:AopPreferences、Mockito
教程添加依赖
dependencies { implementation 'net.bytebuddy:byte-buddy:1.10.1' // implementation 'net.bytebuddy:byte-buddy-android:1.10.1'}
代码
public class ByteBuddyTest { public static void main(String[] args) { User user = new ByteBuddyTest().getProxy(User.class); user.setId(1); user.getId(); } private T getProxy(Class clazz) { Class
关注
打赏