日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > Android >内容正文

Android

【AOP 面向切面编程】Android Studio 使用 AspectJ 监控方法运行 ( 定义连接点注解 | 定义 Aspect 切面 | 定义切入点 | 逐个处理切入点的各个连接点 )

發(fā)布時間:2025/6/17 Android 24 豆豆

文章目錄

  • 一、定義 Join Point 連接點注解
  • 二、定義 Aspect 切面
    • 1、定義 Aspect 切面
    • 2、定義 Aspect 切面
    • 3、逐個處理切入點的各個連接點
    • 4、完整 Aspect 切面代碼
  • 三、使用 AspectJ 埋點并監(jiān)控方法性能





一、定義 Join Point 連接點注解



要監(jiān)控哪些方法 , 首先要對該方法添加注解 , 該注解標記哪些方法是 Join Point 連接點 , 所有被該注解標記的方法構(gòu)成 一組 Join Point 連接點 , 即 Point Cut 切入點 ;

package com.example.aop_demo;import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target;/*** 該注解標記哪些方法是 Join Point 連接點* 所有被該注解標記的方法構(gòu)成 一組 Join Point 連接點 , 即 Point Cut 切入點*/ @Retention(RetentionPolicy.RUNTIME) // 注解保留到運行時 @Target(ElementType.METHOD) // 注解作用于方法上 public @interface Monitor {String value(); }

注解的用法如下 : 如果想要監(jiān)控下面的 public void textClick(View view) 方法 , 在該方法上添加 @Monitor 注解即可 ;

@Monitor("textClick")public void textClick(View view) {// 休眠 500 msSystemClock.sleep(500);}



二、定義 Aspect 切面




1、定義 Aspect 切面


Aspect 切面 : Java 中的類聲明是 對事物的抽象 , AspectJ 中的 Aspect 切面就是 對切面的抽象 , 其中包含了 Point Cut 切入點 和 Advice 通知 ; 使用 @Aspect 注解修飾 ;

/*** 定義 Aspect 切面*/ @Aspect public class MonitorAspect { }

2、定義 Aspect 切面


Point Cut 切入點 : 一組 Join Point 連接點 , 通過 邏輯關(guān)系 / 正則表達式 / 通配符 等關(guān)系組合 , 定義了 Advice 通知發(fā)生的位置 ;


解析 "execution(@com.example.aop_demo.Monitor * *(..))" 匹配規(guī)則 :

  • @com.example.aop_demo.Monitor 表示帶該注解的方法
  • 第 1 個 * 表示在所有包下面
  • 第 2 個 * 表示在所有類下面
  • (..) 表示所有方法 , 參數(shù)不限

整體含義 : 所有的包 所有的類 中 , 帶有 @com.example.aop_demo.Monitor 注解的方法 , 都是 Pointcut 切入點 , 每個方法都是一個 JoinPoint 連接點 ;


/*** 定義切入點* "execution(@com.example.aop_demo.Monitor * *(..))" 表示* 帶有 @com.example.aop_demo.Monitor 注解的* 所有包下面的 所有類中的 所有方法, 方法參數(shù)不限* 上述方法組成 切入點 , 每個方法都是一個 Join Point 連接點** execution(@com.example.aop_demo.Monitor * *(..)) 解讀* - @com.example.aop_demo.Monitor 表示帶該注解的方法* - 第 1 個 * 表示在所有包下面* - 第 2 個 * 表示在所有類下面* - (..) 表示所有方法 , 參數(shù)不限** 所有的包 所有的類 中 , 帶有 @com.example.aop_demo.Monitor 注解的方法 , 都是 Pointcut 切入點* 上述每個方法都是一個 Join Point 連接點*/@Pointcut("execution(@com.example.aop_demo.Monitor * *(..))")public void pointCut(){}

3、逐個處理切入點的各個連接點


@Around("pointCut()") 注解中傳入的注解屬性是 切入點 的名稱 , 就是上面定義的 public void pointCut(){} 方法對應的 Pointcut 切入點 ;


獲取 JoinPoint 連接點 對應 方法的相關(guān)屬性 :

  • 獲取方法上的注解 , 以及注解屬性 : 首先獲取方法簽名 , 在回去方法簽名對應的 Method 對象 , 獲取該對象上的注解 , 根據(jù)注解調(diào)用注解中定義的獲取屬性的接口方法 ;
// 獲取方法上 @Monitor("onClick") 注解中的注解屬性 字符串// 獲取被 @Monitor("onClick") 注解修飾的方法的 方法簽名MethodSignature signature = (MethodSignature) joinPoint.getSignature();// 根據(jù)方法簽名獲取方法// 然后獲取方法上的 @Monitor 注解Monitor annotation = signature.getMethod().getAnnotation(Monitor.class);// 獲取 @Monitor("onClick") 注解中的注解屬性String value = annotation.value();
  • 獲取方法名稱 : signature.getDeclaringType() 就是方法所在的類的字節(jié)碼類對象 , 然后調(diào)用 getSimpleName 方法即可獲取類名 ;
// 獲取方法名稱String className = signature.getDeclaringType().getSimpleName();
  • 獲取方法所在類名稱 : 直接調(diào)用方法簽名的 getName 方法 , 即可獲取方法名 ;
// 獲取方法所在的類名String methodName = signature.getName();

調(diào)用 joinPoint.proceed() 方法 , 可同步執(zhí)行該具體的方法 , 方法的上下可以進行用戶自己的埋點業(yè)務邏輯 , 如統(tǒng)計方法執(zhí)行耗時等操作 ;

// 執(zhí)行具體的方法result = joinPoint.proceed();

代碼示例 :

/*** 逐個處理 Pointcut 切入點 中的 JoinPoint 連接點* 一個一個處理** @Around("pointCut()") 注解中傳入的注解屬性是* 切入點的名稱 , 就是上面定義的 public void pointCut(){} 方法** @param joinPoint* @return*/@Around("pointCut()")public Object processJoinPoint(ProceedingJoinPoint joinPoint) {Object result = null;try {// 獲取方法上 @Monitor("onClick") 注解中的注解屬性 字符串// 獲取被 @Monitor("onClick") 注解修飾的方法的 方法簽名MethodSignature signature = (MethodSignature) joinPoint.getSignature();// 根據(jù)方法簽名獲取方法// 然后獲取方法上的 @Monitor 注解Monitor annotation = signature.getMethod().getAnnotation(Monitor.class);// 獲取 @Monitor("onClick") 注解中的注解屬性String value = annotation.value();// 獲取方法名稱String className = signature.getDeclaringType().getSimpleName();// 獲取方法所在的類名String methodName = signature.getName();// 記錄方法執(zhí)行開始時間long startTime = System.currentTimeMillis();// 執(zhí)行具體的方法result = joinPoint.proceed();// 記錄方法執(zhí)行結(jié)束時間long endTime = System.currentTimeMillis();Log.i(TAG, "執(zhí)行 " + className + " 中的 " + methodName +" 方法花費了 " + (endTime - startTime) + " ms , 注解屬性為 " + value );} catch (Throwable throwable) {throwable.printStackTrace();}return result;}

4、完整 Aspect 切面代碼


package com.example.aop_demo;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.aop_demo.Monitor * *(..))" 表示* 帶有 @com.example.aop_demo.Monitor 注解的* 所有包下面的 所有類中的 所有方法, 方法參數(shù)不限* 上述方法組成 切入點 , 每個方法都是一個 Join Point 連接點** execution(@com.example.aop_demo.Monitor * *(..)) 解讀* - @com.example.aop_demo.Monitor 表示帶該注解的方法* - 第 1 個 * 表示在所有包下面* - 第 2 個 * 表示在所有類下面* - (..) 表示所有方法 , 參數(shù)不限** 所有的包 所有的類 中 , 帶有 @com.example.aop_demo.Monitor 注解的方法 , 都是 Pointcut 切入點* 上述每個方法都是一個 Join Point 連接點*/@Pointcut("execution(@com.example.aop_demo.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") 注解中的注解屬性 字符串// 獲取被 @Monitor("onClick") 注解修飾的方法的 方法簽名MethodSignature signature = (MethodSignature) joinPoint.getSignature();// 根據(jù)方法簽名獲取方法// 然后獲取方法上的 @Monitor 注解Monitor annotation = signature.getMethod().getAnnotation(Monitor.class);// 獲取 @Monitor("onClick") 注解中的注解屬性String value = annotation.value();// 獲取方法名稱String className = signature.getDeclaringType().getSimpleName();// 獲取方法所在的類名String methodName = signature.getName();// 記錄方法執(zhí)行開始時間long startTime = System.currentTimeMillis();// 執(zhí)行具體的方法result = joinPoint.proceed();// 記錄方法執(zhí)行結(jié)束時間long endTime = System.currentTimeMillis();Log.i(TAG, "執(zhí)行 " + className + " 中的 " + methodName +" 方法花費了 " + (endTime - startTime) + " ms , 注解屬性為 " + value );} catch (Throwable throwable) {throwable.printStackTrace();}return result;} }



三、使用 AspectJ 埋點并監(jiān)控方法性能



監(jiān)控 public void textClick(View view) 方法性能 , 在該方法上使用 @Monitor 注解 , 該注解已經(jīng)被定義為切入點 , 所有的包 所有的類 中 , 帶有 @com.example.aop_demo.Monitor 注解的方法 , 都是 Pointcut 切入點 , 應用執(zhí)行時 , 會自動執(zhí)行埋點業(yè)務邏輯 , 這里是在方法執(zhí)行前后 , 分別記錄時間 , 最終計算出方法的耗時 ;

package com.example.aop_demo;import androidx.appcompat.app.AppCompatActivity;import android.os.Bundle; import android.os.SystemClock; import android.view.View;public class MainActivity extends AppCompatActivity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);}@Monitor("textClick")public void textClick(View view) {// 休眠 500 msSystemClock.sleep(500);} }

執(zhí)行結(jié)果 : 點擊按鈕 , 觸發(fā) textClick 方法 , 觸發(fā)了埋點邏輯 , 自動計算出了該方法的執(zhí)行耗時 ;

2021-09-22 22:23:04.954 12492-12492/com.example.aop_demo I/MonitorAspect: 執(zhí)行 MainActivity 中的 textClick 方法花費了 501 ms , 注解屬性為 textClick

總結(jié)

以上是生活随笔為你收集整理的【AOP 面向切面编程】Android Studio 使用 AspectJ 监控方法运行 ( 定义连接点注解 | 定义 Aspect 切面 | 定义切入点 | 逐个处理切入点的各个连接点 )的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。