You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 

4.9 KiB

AOP 之 AspectJ 与 ASM

目录

  1. 概述

  2. AspectJ

  3. ASM

    • 前言

    • 自定义 Gradle Plugin

    • Transform API

    • ASM

概述

AOP 即面向切面编程,它是一种编程思想,能对一些事物进行统一处理。在 Android 中,ActivityLifecycleCallbacks 就可以看作是一种 AOP 的实现,它能对 Activity 的生命周期进行统一管理。

AOP 只是一种方法论,它的实现有很多种,动态代理、AspectJ、ASM、Javassist 等等,每个实现方式都要能动态生成字节码,这也是 AOP 的核心。

这里推荐一篇网易的 AOP技术在客户端的应用与实践

这里只介绍 AspectJ 和 ASM,Aspect 上手简单,与 Java 完全互操作,ASM 更加灵活,短小精悍,性能没得说,毫不夸张的说,ASM 无所不能,可以看作是 AOP 的终极方案,但是上手还是需要一点操作的。

AspectJ

AspectJ 使用简单,熟悉了切点表达式就能直接上手了。

入门看一下两篇就够了:

AOP AspectJ 字节码 语法 MD

关于AspectJ,你需要知道的一切

这时候就能简单的写一些 Demo 了,但是显然还不够,你还需要写一些实际的工程,才能更加深刻的理解 AspectJ 到底能做什么有意思的事。

首推 JakeWharton 的 hugo,拥有近 7K star,这个库是用来打印方法耗时、方法参数等的,说出来你可能不信,整个 Project 只有五个类,你完全可以对照自己写一个。

然后是一个 QuickPermissions 的库,是用来解决动态权限的,最初是在 Medium 上看的一篇文章,原文地址: the-easiest-way-to-integrate-run-time-permissions-in-android,虽然是 Kotlin 写的,你可以试试用 Java 写,核心思想就那些。

除此之外,AspectJ 还能解决一些系统 bug,比如 Toast 不弹出等等,相见:Toast与Snackbar的那点事

虽然 AspectJ 实现原理是字节码插桩,但是实际上你会发现,你完全不需要任何字节码基础就能上手了。

ASM

ASM 是一个广泛使用的字节码操作库,前面之所以 ASM 需要一点操作,是因为你需要熟悉字节码,还有一些 ASM 中各种 API 之间的关系。其次,既然是操作字节码的,那我们肯定需要先拿到字节码,这就涉及到了 Gradle Transform API 了。但是使用 Gradle Transform API 是依赖于 Gradle Plugin 的,所以可以看出想学 ASM,还是需要很多前置知识的。

字节码基础

《深入理解 Java 虚拟机》第六章。

自定义 Gradle Plugin

这里就只能委屈你看我写的 Gralde Plugin 入门指南Gralde Plugin 实践之 TinyPng Plugin

Transform API

应用在构建的时候,首先是通过 javac 将源码编译成 class 文件,然后 class 文件再经过 dx 工具生成 dex 文件。而 Transform 就可以干预打包流程,在 class 转 dex 的时候对 class 进行再处理,修改字节码或插入字节码。

这里不得不放出旧版本的 Gradle 构建流程图:

Gradle 内置的 Transform(Task)有 mergeManifest、Proguard 等等,和我们自定义的 Transform 形成了一个 Trasnform 链,我们定义的 Transform 会首先执行:

图片来源:https://juejin.im/entry/577b03438ac2470061afb130

ASM

刚开始学 ASM 的时候,我还是建议先在 IDEA 里面先写一些 Demo,比如给类添加一个方法、给已有方法添加代码、删除已有方法等;

官方中文文档:ASM4 使用指南

这里推荐:手摸手增加字节码往方法体内插代码

然后就可以试着用 ASM 实现 hugo 了,推荐:ASM实战统计方法耗时

到这里就没了,Emmmm,网上大多 ASM 教程都是统计方法耗时,很尴尬。