转载

AOP(面向切面编程)预研报告

  • OOP(面向对象)

    我们需要完成一个任务的时候一般都想着把 一些操作封装成一个类 ,所有的变量和操作都封装到一个类里面,那么这个类就是我们的对象, 我们要实现某个特定的功能,首先也想着在这个对象里面去实现

缺点

比如我们想实现某些不是常用的功能,我们需要去在需要的对象中去一一实现这些功能,并且我们要不断去维护这些功能,一旦多了我们就会很累的。

比如Android中一些按键统计、生命周期统计,特定统计都是比较琐碎的事情,要利用面向对象的思想去实现都不是很完美,这就要求去一一实现,显得很琐碎
  • AOP(面向切面)

    我在使用的时候是关注 具体的方法和功能切入点 ,不需要知道也不用关心所在什么类或者是什么对象,我们只关注功能的实现,具体对象是谁,不关心

2.AOP的实现方式

  • AOP关注的方法功能点,事先不知道所在对象是谁,当然程序的运行都是需要拿到对象在运行的
  • 要在知道方法功能点的前提下拿到对象并执行,这就需要用到Java的动态代理
  • 动态代理可以在不修改对象的情况下,改变对象的逻辑

java的动态代理:

有两个重要的类或接口

一个是 InvocationHandler(Interface)、另一个则是 Proxy(Class),我们可以自己写代码去定义自己的动态代理,去实现AOP,但是 太麻烦了 ,所以需要一个第三方工具

举一个 静态代理 的例子,快速理解代理

public interface HelloInterface {
    void sayHello();
}
public class Hello implements HelloInterface{
    @Override
    public void sayHello() {
        System.out.println("Hello zhanghao!");
    }
}
public class HelloProxy implements HelloInterface{
    private HelloInterface helloInterface = new Hello();
    @Override
    public void sayHello() {
        System.out.println("Before invoke sayHello" );
        helloInterface.sayHello();
        System.out.println("After invoke sayHello");
    }
}
//调用
HelloProxy helloProxy = new HelloProxy();
helloProxy.sayHello();
结果:  
Before invoke sayHello  
Hello zhanghao!  
After invoke sayHello
复制代码

3. 实现AOP的方式对比

AOP方式对比选择

First Header Hook时机 Android中应用场景 优点 缺点
Dexposed 运行时动态hook 滑动流畅度监控,事件执行监控,热修复 可以动态监控和系统通信的各种方法。 不支持5.0以上手机
Xposed 运行时动态hook 同Dexposed 可以动态监控和系统通信的各种方法。 不支持5.0以上手机,必须root
Java Proxy 运行时动态hook hook和系统通信接口例如:插件sdk Java 原生API,没有兼容性问题 只能hook 有Interface的类
AspactJ 编译时修改代码 统计方法执行时长,方法前后注入逻辑 Sprint开源的AOP框架,功能强大。注解很多。基本包括所有的编译时注入方式 需要引入118K的jar
ASM 编译时修改代码 同上 字节码操作库 需要自己写注解和编译脚本。字节码插入编写比较费劲
Javassit 编译时修改代码 同上 基于java反射的字节码操作类库。对比ASM,编写简单 对比ASM,修改类时,执行时间长
  • 主流使用的都是 AspectJ
    • 功能强大
    • 支持编译期和加载时代码注入
    • 易于使用
  • 缺陷
    • 官方不支持Kotlin, 我们项目基本都是Kotlin编写

不过沪江科技开源了自己优化了的AspectJ, 支持Kotlin, 2.8K赞

gradle_plugin_android_aspectjx

  • 开发 gradle_plugin_android_aspectjx 的初衷
  1. 目前的开源库中还没有发现可应用于Android平台的比较好的AOP框架或者工具,虽然xposed,dexposed非常强大,但基于严重的碎片化现状,兼容问题永远是一座无法逾越的大山。
  2. 目前其他的AspectJ相关插件和框架都不支持AAR或者JAR切入的,对于目前在Android圈很火爆的Kotlin更加无能为力。

4. 引入AOP优势和劣势

  • 优势
    • 可以实现无痕埋点
    • AOP天然的面向操作,因此同类型的操作可以快速且无侵入的添加进任何对象
    • 完全解耦, 抽取出来的操作, 跟对象再无关联
  • 劣势
    • 如上表所说, 引入的jar包相对较大
    • 使用沪江科技开源的AOP工具是否持续稳定

不错的讲解

  1. Android AspectJ详解
    • 详解AspectJ
  2. Android AOP 总结
    • AOP方式对比选择
  3. 谈谈Android AOP技术方案
    • AOP方式对比选择
    • 提到不支持Java8
  4. 深入理解Android之AOP
    • 大神详解
  5. Android Aspectj 从入门到实战
    • 点赞

5. 最终结论

暂时不建议使用

  • AOP的最终目的是脱离对象, 对功能点进行抽离
  • 这种抽离暂时还不是我们APP的痛点
  • 但为了让AOP适应我们APP, 我们需要有一些妥协, 如下
  1. 原生AspectJ引入顺畅, 但不支持Kotlin, 我们App几乎全部使用Kotlin编写
  2. 以AspectJ方式支持AOP的暂时只发现沪江科技的aspectjx
  3. 沪江科技的aspectjx虽然支持Kotlin, 但维护人员似乎只有一个, 在我引入的过程中出现过几个,已经在issue里提到过很多次的问题, 但作者并没有理会, 难免让人怀疑维护者对这个项目的热情, 是否会影响到我们后期的使用
原文  https://juejin.im/post/5efae7b3e51d4534a90a7d74
正文到此结束
Loading...