您当前的位置: 首页 >  Java

Java、Android 面向切面编程(AOP)

蔚1 发布时间:2019-09-18 23:31:00 ,浏览量:2

这里会带有 10 种 Java、Android 的 AOP 教程

  1. APT
  2. AspectJ
  3. Javassist
  4. CGLIB
  5. ByteBuddy
  6. JDK 动态代理
  7. ASM
  8. ASMDEX
  9. DexMaker
  10. 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,但是让用户自行试行,提供默认的拦截器。

CGLIB

CGLIB 是一个强大的,高性能,高质量的 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            
关注
打赏
1688896170
查看更多评论
0.0505s