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;@Aspectpublic 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()。