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

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 运维知识 > Android >内容正文

Android

在Android项目中使用AspectJ

發(fā)布時(shí)間:2023/12/1 Android 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 在Android项目中使用AspectJ 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

版權(quán)聲明:本文為博主原創(chuàng)文章,未經(jīng)博主允許不得轉(zhuǎn)載。

轉(zhuǎn)載請表明出處:http://www.cnblogs.com/cavalier-/p/8888459.html

什么是AOP

AOP是 Aspect Oriented Programming 的縮寫,即面向切面編程,和平常遇到的面向?qū)ο驩OP編程不一樣的是,OOP是將功能模塊化對象化,AOP是針對同一類的問題統(tǒng)一化處理。例如做日志埋點(diǎn),性能監(jiān)控,動態(tài)權(quán)限控制等。

AspectJ

AspectJ實(shí)際上是對AOP編程的實(shí)踐,目前還有很多的AOP實(shí)現(xiàn),如ASMDex,但筆者選用的是AspectJ。

在Android項(xiàng)目中使用AspectJ

如果使用原生AspectJ在項(xiàng)目中配置會非常麻煩,在GitHub上有個(gè)開源的SDK gradle_plugin_android_aspectjx基于gradle配置即可。

接入說明

請自行查看開源項(xiàng)目中的接入配置過程

AspectJ 之 Join Points介紹

Join Points在AspectJ中是關(guān)鍵的概念。Join Points可以看做是程序運(yùn)行時(shí)的一個(gè)執(zhí)行點(diǎn),比如:一個(gè)函數(shù)的調(diào)用可以看做是個(gè)Join Points,相當(dāng)于代碼切入點(diǎn)。但在AspectJ中,只有下面幾種執(zhí)行點(diǎn)是認(rèn)為是Join Points:

Join Points說明實(shí)例
method call函數(shù)調(diào)用比如調(diào)用Log.e(),這是一個(gè)個(gè)Join Point
method execution函數(shù)執(zhí)行比如Log.e()的執(zhí)行內(nèi)部,是一處Join Points。注意這里是函數(shù)內(nèi)部
constructor call構(gòu)造函數(shù)調(diào)用和method call 類似
constructor execution構(gòu)造函數(shù)執(zhí)行和method execution 類似
field get獲取某個(gè)變量比如讀取DemoActivity.debug成員
field set設(shè)置某個(gè)變量比如設(shè)置DemoActivity.debug成員
pre-initializationObject在構(gòu)造函數(shù)中做的一些工作。-
initializationObject在構(gòu)造函數(shù)中做的工作。-
static initialization類初始化比如類的static{}
handler異常處理比如try catch 中,對應(yīng)catch內(nèi)的執(zhí)行
advice execution這個(gè)是AspectJ 的內(nèi)容-

Pointcuts 介紹

一個(gè)程序會有多個(gè)Join Points,即使同一個(gè)函數(shù),也還分為call 和 execution 類型的Join Points,但并不是所有的Join Points 都是我們關(guān)心的,Pointcuts 就是提供一種使得開發(fā)者能夠值選擇所需的JoinPoints的方法。

Advice

Advice就是我們插入的代碼可以以何種方式插入,有Before 還有 After、Around。
下面看個(gè)例子:

@Before(“execution(* android.app.Activity.on**(..)))”) public void onActivityMethodBefore(JoinPoint joinPoint) throws Throwable{ }

這里會分成好幾個(gè)部分,我們依次來看:

  • @Before: Advice, 也就是具體的插入點(diǎn)
  • execution:處理Join Point的類型,例如call、execution
  • (* android.app.Activity.on**(..)): 這個(gè)是最重要的表達(dá)式,第一個(gè)*表示返回值,*表示返回值為任意類型,后面這個(gè)就是典型的包名路徑,其中可以包含 *來進(jìn)行通配,幾個(gè) *沒有區(qū)別。同時(shí)這里可以通過&&、||、!來進(jìn)行條件組合。()代表這個(gè)方法的參數(shù),你可以指定類型,例如android.os.Bundle,或者 (..) 這樣來代表任意類型、任意個(gè)數(shù)的參數(shù)。
  • public void onActivityMehodBefore: 實(shí)際切入的代碼。

Before 和 After 其實(shí)還是很好理解的,也就是在Pointcuts之前和之后,插入代碼,那么Android呢,從字面含義上來講,也就是在方法前后各插入代碼,他包含了 Before和 After 的全部功能,代碼如下:

@(“execution(* com.xys.aspectjxdemo.MainActivity.testAOP()))”) public void onActivityMethodAround(ProceedingJoinPoint proceedingJoinPoint) throws Throwable{String key = proceedingJoinPoint.getSignature().toString();Log.d(TAG,”onActivityMethodAroundFirst:”+key);proceedingJoinPoint.proceed();Log.d(TAG,”onActivityMethodAroundSecond:”+key); }

以上代碼中,proceedingJoinPoint.proceed()代表執(zhí)行原始的方法,在這之前、之后,都可以進(jìn)行各種邏輯處理。

自定義Pointcuts

自定義Pointcuts可以讓我們更加精準(zhǔn)的切入一個(gè)或多個(gè)指定的切入點(diǎn)。
首先我們要定義一個(gè)注解類

@Retention(RetentionPolicy.CLASS) @Target({ElementType.CONSTRUCTOR, ElementType.METHOD}) public @interface DebugTrace { }

在需要插入代碼的地方加入這個(gè)注解,例如在MainActivity中加入:

public class MainActivity extends AppCompatActivity{final String TAG = MainActivity.class.getSimpleName();@Overrideprotedcted void onCreate(Bundle savedInstanceState){super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);logTest();}@DebugTracepublic void logTest(){Log.e(TAG,”log test");} }

最后創(chuàng)建切入代碼

@Pointcut(“execution(@com.kun.aspectjtest.aspect.DebugTrace * *..*.*(..))”) public void DebugTraceMethod(){}@Before(“DebugTraceMethod()”) public void beforeDebugTraceMethod(JoinPoint joinPoint) throws Throwable{String key = joinPoint.getSignature().toString();Log.e(TAG, “beforeDebugTraceMethod:”+key); }

Call

在AspectJ的切入點(diǎn)表達(dá)式中,我們前面都是使用的execution,實(shí)際上還有一種類型—call,那么這兩種語法有什么區(qū)別呢?對call來說:

Call (Before) Pointcut{Pointcut Method } Call (After)

對Execution來說:

Pointcut{execution (Before)Pointcut Methodexecution (After) }

Withincode

這個(gè)語法通常來進(jìn)行一些切入點(diǎn)條件的過濾,作更加精確的切入控制,如下:

public class MainActivity extends AppCompatActivity{final String TAG = MainActivity.class.getSimpleName();@Orverideprotected void onCreate(Bundle savedInstanceState){super.onCreate(saveInstanceState);setContentView(R.layout.activity_main);aspectJ1();aspectJ2();aspectJ3();}public void aspectJTest(){Log.e(TAG,”execute aspectJTest");}public void aspectJ1(){aspectJTest();}public void aspectJ2(){aspectJTest();}public void aspectJ3(){aspectJTest();} }

aspectJ1(),aspectJ2(),aspectJ3()都調(diào)用了aspectJTest方法,但只想在aspectJ2調(diào)用aspectJTest時(shí)插入代碼,這個(gè)時(shí)候就需要使用到Pointcut和withcode組合的方式,來精確定位切入點(diǎn)。

@Pointcut(“(call(* *..aspectJTest()))&&withincode(* *..aspectJ2())”) public void invokeAspectJTestInAspectJ2(){ }@Before(“invokeAspectJTestInAspectJ2()”) public void beforeInvokeaspectJTestInAspectJ2(JoinPoint joinPoint) throws Throwable{Log.e(TAG,”method:”+getMethodName(joinPoint).getName()); }private MethodSignature getMethodName(JoinPoint joinPoint){if(joinPoint == null) return null;return (MethodSignature) joinPoint.getSignature(); }

execution 語法

execution()是最常用的切點(diǎn)函數(shù),其語法如下所示:
例如下面這段語法:
@Around(“execution(* *..MainActivity+.on*(..))")
整個(gè)表達(dá)式可以分為五個(gè)部分:

  • execution()是表達(dá)式主體
  • 第一個(gè)*號代表返回類型,*號代表所有的類型。
  • 包名 表示需要攔截的包名,這里使用*.代表匹配所有的包名。
  • 第二個(gè)*號表示類名,后面跟.MainActivity是指具體的類名叫MainActivity。
  • *(..) 最后這個(gè)星號表示方法名,+.代表具體的函數(shù)名,*號通配符,包括括弧號里面表示方法的參數(shù),兩個(gè)dot代表任意參數(shù)。
  • 遇到的錯(cuò)誤

  • 以下錯(cuò)誤可以使用gradle2.2.3解決,由于目前還不適配gradle3.0導(dǎo)致的
  • Error:Execution failed for task ':app:transformClassesWithDexBuilderForDebug'. > Unexpected scopes found in folder '/Users/ram/WorkSpace/AndroidWorkSpace/MyDemo/app/build/intermediates/transforms/AspectTransform/debug'. Required: PROJECT, SUB_PROJECTS, EXTERNAL_LIBRARIES. Found: EXTERNAL_LIBRARIES, PROJECT, PROJECT_LOCAL_DEPS, SUB_PROJECTS, SUB_PROJECTS_LOCAL_DEPS

    轉(zhuǎn)載于:https://www.cnblogs.com/cavalier-/p/8888459.html

    總結(jié)

    以上是生活随笔為你收集整理的在Android项目中使用AspectJ的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

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