【AOP】 Android中使用AspectJX

随笔3个月前发布 老了
35 0 0

背景:在android项目中利用切面编程的思想,使用自定义注解对运行方法的执行性能进行监控。

注:对于配置项,看了几个网上教程,跟着配完并不好使,以下配置项可参考,也不一定能适合你,有问题俺也不一定懂。

1.配置AspectJX

1)根目录下的build.gradle,最上边添加如下配置

buildscript {
    repositories {
        // Insert local test repo here
        mavenCentral()
        jcenter()
        google()
        maven {
            url "https://plugins.gradle.org/m2/"
        }
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:7.0.0'
        classpath 'io.github.wurensen:gradle-android-plugin-aspectjx:3.3.2'
    }
}

123456789101112131415

如图
【AOP】 Android中使用AspectJX

2)模块module下的build.gradle,添加如下

apply plugin: 'io.github.wurensen.android-aspectjx'

1

如图:
【AOP】 Android中使用AspectJX

3)Sync Now
等待下载

2.自定义注解

1)

package com.example.monitorfunc.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;


/**
 * 该注解标记哪些方法是 Join Point 连接点
 *      所有被该注解标记的方法构成 一组 Join Point 连接点 , 即 Point Cut 切入点
 */
@Retention(RetentionPolicy.RUNTIME) // 注解保留到运行时
@Target(ElementType.METHOD) // 注解作用于方法上
public @interface Monitor {
    String value();
}


12345678910111213141516

2)

package com.example.monitorfunc.annotation;

import android.util.Log;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;

/**
 * 定义 Aspect 切面
 */
@Aspect
public class MonitorAspect {

    private static final String TAG = "MonitorAspect";

    /**
     * 定义切入点
     * "execution(@com.example.monitorfunc.annotation.Monitor * *(..))" 表示
     *      带有 @com.example.monitorfunc.annotation.Monitor 注解的
     *      所有包下面的 所有类中的 所有方法, 方法参数不限
     *      上述方法组成 切入点 , 每个方法都是一个 Join Point 连接点
     *
     * execution(@com.example.monitorfunc.annotation.Monitor * *(..)) 解读
     *  - @com.example.monitorfunc.annotation.Monitor 表示带该注解的方法
     *  - 第 1 个 * 表示在所有包下面
     *  - 第 2 个 * 表示在所有类下面
     *  - (..) 表示所有方法 , 参数不限
     *
     *  所有的包 所有的类 中 , 带有 @com.example.monitorfunc.annotation.Monitor 注解的方法 , 都是 Pointcut 切入点
     *      上述每个方法都是一个 Join Point 连接点
     */
    @Pointcut("execution(@com.example.monitorfunc.annotation.Monitor * *(..))")
    public void pointCut(){}

    /**
     * 逐个处理 Pointcut 切入点 中的 JoinPoint 连接点
     *
     * @Around("pointCut()") 注解中传入的注解属性是
     *      切入点的名称 , 就是上面定义的 public void pointCut(){} 方法
     *
     * @param joinPoint
     * @return
     */
    @Around("pointCut()")
    public Object processJoinPoint(ProceedingJoinPoint joinPoint) {
        Object result = null;
        try {
            // 获取被 @Monitor("onClick") 注解修饰的方法的 方法签名
            // joinPoint.getSignature()提供了关于被调用方法或构造器的信息,
            //      用MethodSignature作类型转换,以获取关于方法调用的详细信息,比如方法名、参数类型、返回类型等。
            MethodSignature signature = (MethodSignature) joinPoint.getSignature();

            // 根据方法签名获取方法,然后获取方法上的 @Monitor 注解
            Monitor annotation = signature.getMethod().getAnnotation(Monitor.class);

            // 获取 @Monitor("onClick") 注解中的注解属性
            String value = annotation.value();

            // 获取方法名称
            String className = signature.getDeclaringType().getSimpleName();

            // 获取方法所在的类名
            String methodName = signature.getName();

            // 记录方法执行开始时间
            long startTime = System.currentTimeMillis();

            // 执行具体的方法
            result = joinPoint.proceed();

            // 记录方法执行结束时间
            long endTime = System.currentTimeMillis();

            Log.i(TAG, "执行 " + className + " 中的 " + methodName +
                    " 方法花费了 " + (endTime - startTime) + " ms , 注解属性为 " + value );
        } catch (Throwable throwable) {
            throwable.printStackTrace();
        }
        return result;
    }
}


123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384

3.使用注解

package com.example.monitorfunc;

import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;
import android.view.View;
import android.widget.Toast;

import com.example.monitorfunc.annotation.Monitor;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }

    @Monitor("onClick")
    public void textClick(View view) {
        Toast.makeText(getApplicationContext(), "按钮被点击了", Toast.LENGTH_SHORT).show();
    }
}


1234567891011121314151617181920212223

4.实现结果

【AOP】 Android中使用AspectJX

参考
[1]: https://cloud.tencent.com/developer/article/2251506

© 版权声明

相关文章

暂无评论

您必须登录才能参与评论!
立即登录
暂无评论...