android AOP面向切面编程---AspectJ使用

以下内容仅为个人学习记录

一、配置AspectJ

方法一

使用github上开源的SDK

(1)在项目根目录的build.gradle里依赖AspectJX

dependencies {
        classpath 'com.hujiang.aspectjx:gradle-android-plugin-aspectjx:2.0.8'
        }

(2)在app项目的build.gradle里应用插件

apply plugin: 'android-aspectjx'
//或者这样也可以
apply plugin: 'com.hujiang.android-aspectjx'

以上就完成了配置,以下是一些额外配置

aspectjx {
    //排除所有package路径中包含`android.support`的class文件及库(jar文件)
    exclude 'android.support'
    // 或者织入遍历符合条件的库
    include 'android.support'
    
    //关闭AspectJX功能
    enabled false
}

方法二

(1)自行配置,新建一个gradle文件。然后在app项目的build.gradle引入

// aspectj 编译所需gradle脚本
apply from: 'aspectj-configure-app.gradle'

至于aspectj-configure-app.gradle的内容,大家可以查看项目中的该文件

(2)导入aspectj库的依赖

api 'org.aspectj:aspectjrt:1.8.10'

二、 使用AspectJ

(1)新建一个类,在类顶部加上@Aspect注解

@Aspect
public class TestAspect {
}

(2)编写切入点

~下面的例子就是代表切入点为Activity的onCreate方法

execution(protected void android.app.Activity.onCreate(Bundle))
execution()--用于描述方法
protected--修饰符,“*”代表任意(可省略)
void--返回值类型,“*”代表任意(不能省略)
android.app.Activity.onCreate--完整的方法引用名
(Bundle)--参数类型,多参数用逗号隔开如(int, int);“”代表任意参数,如(, int),即代表第一个参数任意,第二个为整型。
(..) : 这个写法就代表任意个数的参数,任意类型

~所以下面的写法是包含上面的例子

execution(* android.app.Activity.onCreate(..))

~完整的方法引用名使用通配符的写法

android.app.Activity.* -- 该类下任意的方法名
java.io.Serializable+.* -- 实现该接口的类下任意的方法名
android.app.*.* -- 该android.app包下任意类的任意方法名
android.app..*.* -- 该android.app包和其子包下任意类的任意方法名
android.app..Activity.* -- 该android.app包和其子包下所有名字叫Activity的类的任意方法名

~方法名也可以使用通配符

on* -- 以on开头的方法名
*Create -- 以Create结尾的方法名
on*Create -- 以on开头和Create结尾,中间包含任意字符的方法名

~组合切入点表达式

||或运算(符合方法1或方法2)
execution(* android.app.Activity.onCreate(..)) || execution(* android.app.Activity.onResume(..))
&& 且运算(同时实现接口1和接口2)
execution(* (cn.javass.IPointcutService+&& java.io.Serializable+).*(..))
!非运算(除了指定方法以外的方法)
execution(* (!cn.javass..IPointcutService+).*(..))

~使用@Pointcut注解辅助编写切入点

    private static final String POINTCUT_METHOD =
            "execution(* on*Click(..))";
    private static final String POINTCUT_BUTTER_KNIFE =
            "execution(@butterknife.OnClick * *(..))";

    @Pointcut(POINTCUT_METHOD)
    public void methodPointcut() {

    }

    @Pointcut(POINTCUT_BUTTER_KNIFE)
    public void butterKnifePointcut() {

    }

    @Around("methodPointcut() || butterKnifePointcut()")
    public void aroundJoinPoint(ProceedingJoinPoint joinPoint) {
        
    }

以上是比较常用的expression表达式写法,至于还有一些复杂的用法和写法可以参考这篇文章link

(3)AspectJ通知类型(切入时机)

@Before(前置通知)-- 在方法执行前执行

@After(最终通知)-- 方法执行完毕后执行,无论方法中是否出现异常

@Around(环绕通知)-- 替换原有的逻辑,原有逻辑是否继续进行,或是取消,取决于我们@Around方法下的逻辑

@AfterReturning(后置通知)-- 方法正常返回后执行,如果方法中抛出异常,通知无法执行必须在方法执行后才执行,所以可以获得方法的返回值。

@AfterThrowing (抛出异常通知)-- 方法抛出异常后执行,如果方法没有抛出异常,无法执行

    @Before("……")
    public void onMethodBefore(JoinPoint joinPoint){
    }
    
    @After("……")
    public void onMethodAfter(JoinPoint joinPoint){
    }
    
    @Around("……")
    public void onMethodArounde(ProceedingJoinPoint joinPoint){
      joinPoint.proceed(); // 执行原有逻辑
    }
    
    @AfterReturning(value = "……", returning="result")
    public void onMethodAfterReturning(Object result){
    }
    
    @AfterThrowing(value = "……", throwing="ex")
    public void onMethodAfterThrowing(Exception ex){
    }

(4)JoinPoint类介绍

~JoinPoint

Object[] getArgs():获取连接点方法运行时的入参列表
Object getTarget():获取连接点所在的目标对象
String toShortString():获取该目标对象方法命名

~ProceedingJoinPoint(继承JoinPoint子接口,它新增了两个用于执行连接点方法的方法)

Object proceed() throws Throwable:通过反射执行目标对象的连接点处的方法
Object proceed(Object[] args) throws Throwable:通过反射执行目标对象连接点处的方法,不过使用新的入参替换原来的入参

三、项目申请权限的AOP使用

    @RequestPermission(permissions = {Manifest.permission.CAMERA})
    public void startImageCapture(……) {
        
    }
    
    @RequestPermission(requestCode = 100, permissions = {Manifest.permission.CAMERA}, hint = "相机打开失败,没有权限!")
    public void startImageCapture(……) {
        
    }
    
    // 拒绝权限
    @RequestPermissionRefuse
    public void refusePermission(int requestCode) {
        
    }
    
    // 禁止权限
    @RequestPermissionForbid
    public void forbidPermission(int requestCode) {
        
    }
    

AspectJ的API文档

你可能感兴趣的:(android AOP面向切面编程---AspectJ使用)