当前位置: 首页 > news >正文

AspectJ 在 Android 中的完整使用指南

一、环境配置(Gradle 7.0+ 适配)

1. 项目级 build.gradle
// 注意:沪江插件已停更,推荐官方兼容方案
buildscript {dependencies {classpath 'org.aspectj:aspectjtools:1.9.9.1' // AspectJ 工具}
}

2. 模块级 build.gradle

plugins {id 'com.android.application'id 'io.freefair.aspectj' // 官方推荐插件(支持 AGP 7.0+)
}dependencies {implementation 'org.aspectj:aspectjrt:1.9.9.1' // 运行时库
}

兼容性说明:若项目含 Kotlin,添加 id 'io.freefair.aspectj.post-compile-weaving' 插件

二、核心语法详解

1. 切点表达式(Pointcut)
表达式示例含义
execution(public * *(..))所有 public 方法
execution(* com.util.*.*(..))com.util 包下所有方法
@annotation(com.LogTrack)被 @LogTrack 注解的方法
within(com.ui..*)com.ui 包及其子包所有类的方法
call(* android.util.Log.d(..))拦截 Log.d() 的调用(非执行)
2. 通知类型(Advice)
@Before("pointcut()")          // 方法执行前
@After("pointcut()")           // 方法执行后(无论成败)
@AfterReturning(pointcut="", returning="result") // 方法返回后
@AfterThrowing(pointcut="", throwing="ex") // 抛出异常后
@Around("pointcut()")          // 完全控制方法执行(最常用)

三、实战案例

案例 1:自动日志追踪
@Aspect
public class DebugLogAspect {// 切点:标记 @DebugLog 的方法@Pointcut("execution(@com.example.DebugLog * *(..))")public void debugLogPointcut() {}@Around("debugLogPointcut()")public Object logMethod(ProceedingJoinPoint joinPoint) throws Throwable {MethodSignature signature = (MethodSignature) joinPoint.getSignature();String methodName = signature.getMethod().getName();long start = System.currentTimeMillis();Log.d("AspectJ", "▶️ " + methodName + " 开始 | 参数: " + Arrays.toString(joinPoint.getArgs()));Object result = joinPoint.proceed(); // 执行原方法long duration = System.currentTimeMillis() - start;Log.d("AspectJ", "◀️ " + methodName + " 结束 | 耗时: " + duration + "ms | 结果: " + result);return result;}
}
案例 2:权限申请自动化
// 定义权限注解
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface RequirePermission {String[] value(); // 需要申请的权限
}// 切面实现
@Aspect
public class PermissionAspect {@Around("execution(@RequirePermission * *(..)) && @annotation(permission)")public Object checkPermission(ProceedingJoinPoint pjp, RequirePermission permission) throws Throwable {Activity activity = (Activity) pjp.getTarget(); // 获取宿主ActivityString[] perms = permission.value();if (hasPermissions(activity, perms)) {return pjp.proceed(); // 已有权限} else {// 发起权限申请(需配合 ActivityResultLauncher)PermissionRequester.request(activity, perms, () -> {try { pjp.proceed(); } catch (Throwable ignored) {} });return null; // 阻断原方法执行}}private boolean hasPermissions(Context ctx, String... perms) {for (String perm : perms) {if (ContextCompat.checkSelfPermission(ctx, perm) != PERMISSION_GRANTED) return false;}return true;}
}

四、高频问题解决方案

问题 1:织入(Weaving)失效

排查步骤

  1. 检查是否应用了 AGP 7.0+ 的兼容插件

  2. 确认 aspectjrt 版本一致性

  3. 使用命令检查织入结果:

./gradlew clean assembleDebug --debug | grep "ajc"
问题 2:Lambda 表达式支持

在 build.gradle 中添加:

aspectj {excludeJar "com.android.support" // 排除冲突库weaveInfo = trueaddSerialVoid = true // 修复 Lambda 支持
}

五、性能优化建议

  1. 避免在切面中执行耗时操作
    (如:IO 读写、网络请求)

  2. 精确限定切点范围

// 劣质写法:扫描全包
@Pointcut("execution(* com.app..*.*(..))")// 优化写法:精确到类
@Pointcut("within(com.ui.HomeActivity) || within(com.service.*Impl)")

        编译时排除第三方库

aspectj {exclude "androidx.*", "com.google.*" 
}

六、AspectJ vs 其他方案对比

方案集成难度性能功能完整性适用场景
AspectJ★★★☆⚡⚡⚡✅ 100%需要完整 AOP 支持
ASM★★★★☆⚡⚡⚡⚡⚠️ 手动实现高性能字节码操作
动态代理★★☆❌ 仅限接口简单运行时拦截
注解处理器★★★☆⚡⚡⚠️ 无执行期生成代码替代运行时逻辑

💡 结论:AspectJ 仍是 Android 平台功能最完备的 AOP 方案,适合复杂横切逻辑。

七、高级技巧:编译时代码注入

在 @Around 中动态修改参数:

@Around("execution(* com.payment.process(..))")
public Object encryptPayment(ProceedingJoinPoint pjp) throws Throwable {Object[] args = pjp.getArgs();if (args.length > 0 && args[0] instanceof PaymentRequest) {PaymentRequest request = (PaymentRequest) args[0];request.setCardToken(AES.encrypt(request.getCardNumber())); // 自动加密args[0] = request; // 替换参数}return pjp.proceed(args); // 传入新参数
}

通过本指南,你可快速掌握 AspectJ 在 Android 中的工程化应用。建议从 日志监控权限管理 等场景入手,逐步深入字节码层优化。

http://www.xdnf.cn/news/945991.html

相关文章:

  • 博睿数据×华为, 共筑智慧金融新未来
  • UE5 学习系列(一)创建一个游戏工程
  • 机器学习监督学习实战六:五种算法对新闻组英文文档进行文本分类(20类),词频统计和TF-IDF 转换特征提取方法理论和对比解析
  • 【安全篇】金刚不坏之身:整合 Spring Security + JWT 实现无状态认证与授权
  • 让 Kubernetes (K8s) 集群 使用 GPU
  • 阿里云Ubuntu 22.04 64位搭建Flask流程(亲测)
  • k8s从入门到放弃之Service负载均衡
  • AWS vs 阿里云:功能、服务与性能对比指南
  • 轻量级关键点 blaze pose 2025
  • SpringCloud优势
  • 软件工程教学评价
  • CentOS 7 部署 Samba 使用虚拟用户笔记
  • centos 7 部署awstats 网站访问检测
  • GO语言---init函数
  • Vue 3 实战:【加强版】公司通知推送(WebSocket + token 校验 + 心跳机制)
  • 软件工程 期末复习
  • 【Linux开发】Hi3516dv300-DC-182型开发板显示开机logo的相关操作
  • 统计学(第8版)——假设检验学习笔记(考试用)
  • 阿里云服务器 篇十七:网站悬浮球
  • Jenkins构建时出现报错`ERROR: Failed to install JDK. Exit code=2`的终极解决方案
  • 2025年- H79-Lc187--118. 杨辉三角(找规律)--Java版
  • Java性能测试工具列举
  • 相机Camera日志实例分析之一:相机Camx【前置慢动作分辨率切换720P、1080P录制】单帧流程日志详解
  • PolyU Palmprint Database掌纹识别数据集预处理(踩坑版)
  • Maven从入门到精通指南
  • Linux边缘智能:物联网的终极进化
  • 职坐标物联网全栈开发全流程解析
  • 算法刷题-回溯
  • SpringCloudGateway 自定义局部过滤器
  • WEB3全栈开发——面试专业技能点P8DevOps / 区块链部署