AspectJ在Android 的应用耗时统计
文章转自:https://mp.weixin.qq.com/s/EaHrD4A8TeADDPUQEoKb-g
概述
AspectJ 是 Java 语言 AOP(面向切面编程)的一种实现方案。
AspectJ 有两种实现方式:
- 使用 Java 语言和注解,然后通过 AspectJ 提供的编织器,编织代码到目标 class 文件;
- 直接使用 AspectJ 语言编写,然后使用 ajc 编译器用来编译 aj 文件,生成 java 标准的 class 文件。
AspectJ 语言的语法和 Java 一样,只是比 Java 语言多了一些关键字,但由于 Android Studio 并没有提供 AspectJ 语法的支持,所以在 Android 开发中使用 AspectJ 只能使用注解的方式来实现。
下面通过注解的实现方式来解释一些基本的概念。
基本概念
Aspect(切面)
一个切面是一个独立的功能实现,一个程序可以定义多个切面,定义切面需要新建一个类并加上 @Aspect
注解。
例如:SampleAspect 就是一个切面 ,这个切面实现了打印所有 Activity 中 onCreate()
方法耗时的功能。
1 |
|
JointPoint(链接点)
链接点代表了程序中可以切入代码的位置,包括函数的调用和执行,类的初始化,异常处理等,链接点就是利用 AspectJ 可以侵入修改的地方。
例如 Activity 中 onCreate()
方法的调用和执行,Activity 的初始化,构造方法的执行等,可以在这些 JointPoint(链接点)切入自己想要的代码。
PointCut(切点)
切点是具体的链接点,切点定义了需要织入代码的链接点,切点的定义有专门的语法。
例如:下面这个就代表一个切点,这个切点表示了所有 Activity 以及其子类的 onCreate()
方法的执行。
1 | @Pointcut("execution(void android.support.v4.app.FragmentActivity+.onCreate(..))") |
Advice(通知)
通知代表对切点的监听,可以在这里编写需要织入的代码。通知包括:@Before
方法执行前,@After
方法执行后,@Aroun
d 方法执行前后。
例如:下面分别表示了切点 activityOnCreate 的执行前、执行后、执行前后的监听,其中 @Around
需要自己处理方法的执行,并且必须放在 @Before
和 @After
之前。
1 |
|
匹配表达式
上面讲到了定义切点时需要用到专门的语法:匹配表达式。匹配表达式分为以下几种类型:
方法类型
1 | 1[!] [@Annotation] [public,protected,private] [static] [final] 返回值类型 [类名.]方法名(参数类型列表) [throws 异常类型] |
定义方法切点时需要用到方法类型的匹配表达式,其中 execution()
代表了方法的执行,[]
中的内容为可选。
如果是构造方法只需要把方法名替换为 new。例如:
1 |
|
Android集成AspectJ
在 AndroidStudio 中使用 AspectJ 需要分三步:
引入第三方注解包
在需要编写切面的 Module 中引入 'org.aspectj:aspectjrt:1.8.7'
里面包含了注解等代码。
1 | dependencies { |
引入 Gradle 插件
使用 AspectJ 的功能,必须通过插件来处理插入的代码。Gradle 插件的作用是处理切面类,植入代码。目前针对 Android 来说并没有官方 Gradle 插件,需要自己编写或者使用第三方成熟的插件。
下图所示是本地自定义的一个 Gradle 插件,使用这种本地 Gradle 插件的方式,则只需要在主 Module 的 build.gradle
中引入插件即可,具体实现细节下个章节会讲到。
编写切面类
编写切面类,编写切点和通知代码
Gradle 插件的实现
Gradle 插件实现如果不需要发布插件,则可以再编写本地插件。自定义插件的方式这里不再赘述,感兴趣的小伙伴可以参考官方文档。