写点什么

初识 AspectJ ~

作者:阿策小和尚
  • 2021 年 12 月 13 日
  • 本文字数:1946 字

    阅读完需:约 6 分钟

    小菜在尝试 Android 性能优化过程中,需要统计的监测各个方法执行调用时间,以及对应 Systrace 生成时;较为优雅的方式就是采用 AOP 切片模式,而 AOP 模式中较为成熟和简单的当属 AspectJ;小菜进行简单集成与测试;

AspectJ

基本简介

    AOP(Aspect Oriented Programming) 是一种面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术;可以通过 AOP 对业务逻辑进行整体的切面拆分,却又不影响业务逻辑,提高了开发效率和可重用性;


    AspectJ 适用于 Java 平台,是使用较为广泛的 AOP 切面方案;提供了纯 Java 语言实现,通过注解的方式,在编译期进行代码注入;即在编译阶段,就对目标类进行修改,得到的 .class 文件已经是修改过的,生成静态的 AOP 代理类;小菜刚了解 AspectJ,需要了解几个最基本的概念;

1. Aspect

    AspectAOP 中的切面文件,一般将需要在注解开发的 Java 类文件顶部注明 @Aspect,不能修饰接口;

2. JoinPoint

    JoinPoint 作为连接点,是程序运行时的一些执行点;例如方法调用时,或读写变量以及异常处理等;官网 介绍非常详细,小菜提醒注意 call() & execution() 这两个方法;


    小菜了解 call() & execution() 织入对象不同,call() 是在指定方法被调用时调用,而 execution() 是在方法执行内部时被调用;

3. Pointcut

    Pointcut 是具体的切入点,目标是提供一种方法,使开发者可以选择感兴趣的 JoinPoint



4. Advice

    Advice 用于逻辑处理时切面功能的实现;注解修饰的方法需为 publicAround 使用的是 ProceedingJoinPoint,其他的是 JoinPoint



集成测试

    AspectJ 的集成非常简单,仅需简单的几个步骤:

1. 根目录 dependencies 中引入插件;

classpath 'com.hujiang.aspectjx:gradle-android-plugin-aspectjx:2.0.5'
复制代码

2. 在应用 module 中应用插件;

apply plugin: 'android-aspectjx'
复制代码

3. 编辑记录时间切片的 AOP 文件;

@Aspectpublic class TimeAOP {
@Around("call(* com.package.name.Application.**(..))") public void getApplicationTime(ProceedingJoinPoint joinPoint) { long time = System.currentTimeMillis(); try { joinPoint.proceed(); } catch (Throwable throwable) { throwable.printStackTrace(); } Log.e("TimeAOP:", "Application " + joinPoint.getSignature().getName() + " Time = " + (System.currentTimeMillis() - time)); }
@Pointcut("execution(* com.package.name.MainActivity.**(..))") public void callMethod() {
}
@Around("callMethod()") public void getActivityTime(ProceedingJoinPoint joinPoint) { long time = System.currentTimeMillis(); try { joinPoint.proceed(); } catch (Throwable throwable) { throwable.printStackTrace(); } Log.e("TimeAOP:", "Activity " + joinPoint.getSignature().getName() + " Time = " + (System.currentTimeMillis() - time)); }}
复制代码

4. 在应用 module 中配置排除冲突的 aspectjx

android {    ...    aspectjx {        enabled true        include "packagename"        exclude 'com.google','com.appsflyer','com.android'  // 可根据具体的业务确定是否排除    }}
复制代码

5. 在应用 module 中添加,此步骤可省略

// 不是必须的,但是为了有时候去掉上面插件不报错就需要增加api 'org.aspectj:aspectjrt:1.9.4'
复制代码

问题 & 修复

    AspectJ 的集成只有简单的几步,但小菜却折腾了很久;小菜先在 Demo 中集成测试,一切正常;但是应用在历史项目中,却坎坷颇多;

Q1:[TAG] Failed to resolve variable '${httpcore.version}'


A1:

    其原因是小菜未在 module 中配置 aspectjx,添加对应的 aspectjx 配置即可;

Q2:Cause: zip file is empty


A2:

    根据问题,小菜以为是 Gradle 版本不一致,反复 clean / rebuild 多次后依旧不生效,同时在其他 module 中添加 'android-aspectjx',结果并不生效;最终小菜发现自己编辑的 AOP 切片文件格式有误,少了一个 * 导致的;因此小菜建议 AOP 文件先编辑最简单方法,逐步完善操作;



    AspectJ 的功能非常强大,小菜刚学习很多切入规则还不熟悉,仅尝试了最基本的 @Around 方式获取方法的耗时时间;小菜建议在编辑规则过程中,多审查几遍,防止出现因规则错误导致的不容易查找的崩溃;


    通过这次学习,小菜深得体会,不管看似多么简单的应用,只有实际上手操作才能体会深刻,官网是最详细的学习资料;如有错误,请多多指导!


来源: 阿策小和尚

发布于: 7 小时前阅读数: 5
用户头像

还未添加个人签名 2021.05.13 加入

Android / Flutter 小菜鸟~

评论

发布
暂无评论
初识 AspectJ ~