乐趣区

关于android:AndroidAspectJX学习笔记

AspectJX 学习笔记

参考文档:

Introduction to AspectJ

Github: AspectjDemo

Android 监测用户行为之中 AOP 编程之 AspectJ 实战 作者:weixin_33726943

Android 中的 AOP 的实现及 AspectJ 的应用 作者:岩浆李的游鱼

深刻了解 Android 之 AOP 作者:阿拉神农

  • Join Points(连接点):简称 JPoints,是 AspectJ 的核心思想之一,把程序的整个执行过程划分成几个关键点,包含构造方法调用,调用办法,办法执行,抛出异样等。这些关键点能够作为 Join Points,将想要执行的内容插入到这些机会中。
  • Pointcuts(切入点):指定相应 Advice 须要插入的地位。
  • Advice(告诉):指定代码将注入到 Pointcuts 的什么地位。
  • Aspect(切面):Pointcut 和 Advice 组合到一起,造成了一个明确的地位,也就是切面。

一、Pointcuts 切入点

用来形容 JPoint 注入点的一段表达式,比方:调用 Animal 类 fly 办法的中央,call(* Animal.fly(..))。

机会 命令
函数执行(在函数外部) execution(MethodPattern)
函数调用(调用函数的地位) call(MethodPattern)
构造函数执行 execution(ConstructorPattern)
结构函数调用 call(ConstructorPattern)
动态初始化 staticinitialization(TypePattern)
读取属性 get(FieldPattern)
设定属性 set(FieldPattern)
异样解决(对应 catch 内的执行) handler(TypePattern)
Advice 执行时 adviceexecution()

1、明确指定切入点

办法签名为 void Point.setX(int),Point 的 setX 办法,入参是 1 个 int 类型,返回值为 void

call(void Point.setX(int))

2、应用条件运算符指定切入点

能够通过 &&,||,!进行逻辑运算。

call(void Point.setX(int)) ||
call(void Point.setY(int))

3、应用通配符指定切入点

筛选出 Figure 类,函数名以 make 结尾,任意参数,返回值为 void 的办法。

call(void Figure.make*(..))

4、限定拜访权限的切入点

限定 Figure 类,任意函数名,任意参数,任意返回值,public 办法。

call(public * Figure.* (..))

二、Advice 倡议

常见的有 Before、After、Around 等,示意代码执行前、执行后、替换指标代码,也就是在 Pointcut 何处注入代码。

注解 用处
Before 在执行 JPoint 之前
After 在执行 JPoint 之后
Around 替换原须要执行的代码,如果须要执行源代码,能够应用 jointPoint.proceed() 办法。
AfterReturning 失常 return 时
AfterThrowing 抛出异样时

三、AspectJX 应用

AspectJX 是沪江网开源的一个反对 Android 的 AspectJ 库。Github:gradle_plugin_android_aspectjx

1、环境配置

  • 在根目录的 build.gradle 减少 AspectJX 的依赖。
dependencies {classpath 'com.hujiang.aspectjx:gradle-android-plugin-aspectjx:2.0.8'}
  • 批改须要应用 AspectJX 的模块的 build.gradle。
dependencies {
    // ..
    implementation 'org.aspectj:aspectjrt:1.9.5'
    // ..
}

apply plugin: 'android-aspectjx'

aspectjx {
    // 排除局部门路
    exclude 'android'
    exclude 'com.alibaba'
}

2、创立 Aspect 类

须要在类上注解 @Aspect,函数上注解须要注入的门路

returning 参数能够指明返回值。

package com.irisleon.fridge.util;

import android.util.Log;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;

@Aspect
public class TrackHelper {
   private static final String TAG = "TrackHelper";

   @Before("execution(* com.irisleon.fridge.*.*.*(..)) || execution(* com.irisleon.fridge.*.*(..))")
   public void DebugFunctionLog(JoinPoint joinPoint) throws Throwable {Log.d(TAG, "----> FuncTrace:" + joinPoint.getSignature());
      Log.d(TAG, "At:" + joinPoint.getSourceLocation());
      for (Object item : joinPoint.getArgs()) {if (item != null) {Log.d(TAG, "Arg:" + item.toString());
         }
      }
   }

   @AfterReturning(pointcut = "execution(* com.irisleon.fridge.*.*.*(..)) || execution(* com.irisleon.fridge.*.*(..))",
         returning = "retVal")
   public void DebugReturnLog(JoinPoint joinPoint, Object retVal) throws Throwable {Log.d(TAG, "<---- FuncTrace:" + joinPoint.getSignature());
      if (retVal != null) {Log.d(TAG, "Return:" + retVal);
      }
   }
}

3、成果展现

4、应用场景

1)收集用户点击事件,入参。不须要侵入式批改每一个点击事件,只须要对立监听 onClick,onTouch 等事件。
2)判断某个函数是否有调用权限。例如 @Around 注解。判断用户是否曾经登录。如果未登录,或者没有权限,则不持续进行解决。如果能够持续操作,调用 jointPoint.proceed()。

退出移动版