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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

框架:AspectJ

發布時間:2025/3/21 编程问答 14 豆豆
生活随笔 收集整理的這篇文章主要介紹了 框架:AspectJ 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

AOP雖然是方法論,但就好像OOP中的Java一樣,一些先行者也開發了一套語言來支持AOP。目前用得比較火的就是AspectJ了,它是一種幾乎和Java完全一樣的語言,而且完全兼容Java(AspectJ應該就是一種擴展Java,但它不是像Groovy[1]那樣的拓展。)。當然,除了使用AspectJ特殊的語言外,AspectJ還支持原生的Java,只要加上對應的AspectJ注解就好。所以,使用AspectJ有兩種方法:

  • 完全使用AspectJ的語言。這語言一點也不難,和Java幾乎一樣,也能在AspectJ中調用Java的任何類庫。AspectJ只是多了一些關鍵詞罷了。
  • 或者使用純Java語言開發,然后使用AspectJ注解,簡稱@AspectJ。

AspectJ的配置可以參考另一篇文章Android中使用AspectJ

Join Points介紹

Join Points是AspectJ中的一個關鍵概念。Join Points可以看作是程序運行時的一個執行點,比如:一個函數的調用可以看作是個Join Points,如Log.e()這個函數,e()可以看作是個Join Points,而調運e()的函數也可以認為是一個Join Points;設置一個變量,或者讀取一個變量也可以是個Join Points;for循環也可以看作是Join Points。

理論上說,一個程序中很多地方都可以被看做是Join Points,但是AspectJ中,只有下面所示的幾種執行點被認為是Join Points:

Join Points說明示例
method call函數調用比如調用Log.e(),這是一處JPoint
method execution函數執行比如Log.e()的執行內部,是一處Join Points。注意它和method call的區別。method call是調用某個函數的地方。而execution是某個函數執行的內部。
constructor call構造函數調用和method call類似
constructor execution構造函數執行和method execution類似
field get獲取某個變量比如讀取DemoActivity.debug成員
field set設置某個變量比如設置DemoActivity.debug成員
pre-initializationObject在構造函數中做得一些工作。?
initializationObject在構造函數中做得工作?
static initialization類初始化比如類的static{}
handler異常處理比如try catch(xxx)中,對應catch內的執行
advice execution這個是AspectJ的內容,稍后再說?

這里列出了AspectJ所認可的JoinPoints的類型。實際上,也就是你想把新的代碼插在程序的哪個地方,是插在構造方法中,還是插在某個方法調用前,或者是插在某個方法中,這個地方就是Join Points,當然,不是所有地方都能給你插的,只有能插的地方,才叫Join Points。

Pointcuts介紹

一個程序會有多個Join Points,即使同一個函數,也還分為call和execution類型的Join Points,但并不是所有的Join Points都是我們關心的,Pointcuts就是提供一種使得開發者能夠選擇自己需要的JoinPoints的方法。

Advice

Advice就是我們插入的代碼以何種方式插入,有Before還有After、Around。

看個例子

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

這里會分成幾個部分,我們依次來看:

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

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

@Around("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()代表執行原始的方法,在這之前、之后,都可以進行各種邏輯處理。

自定義Pointcuts(注解形式)

自定義Pointcuts可以讓我們更加精確的切入一個或多個指定的切入點。

首先我們要定義一個注解類

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

在需要插入代碼的地方加入這個注解。如在MainActivity中加入,

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

最后,創建切入代碼

@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); }

log如下

在AspectJ的切入點表達式中,我們前面都是使用的execution,實際上,還有一種類型——call,那么這兩種語法有什么區別呢,對于Call來說:

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

對于Execution來說:

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

withincode

這個語法通常來進行一些切入點條件的過濾,作更加精確的切入控制。如下

public class MainActivity extends AppCompatActivity {final String TAG = MainActivity.class.getSimpleName();@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);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()都調用了aspectJTest方法,但只想在aspectJ2調用aspectJTest時插入代碼,這個時候就需要使用到Pointcut和withincode組合的方式,來精確定位切入點。

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

log如下

04-02 23:44:40.681 12107-12107/ E/MainActivity: execute aspectJTest 04-02 23:44:40.681 12107-12107/ E/AspectTest: method:aspectJTest 04-02 23:44:40.681 12107-12107/ E/MainActivity: execute aspectJTest 04-02 23:44:40.681 12107-12107/ E/MainActivity: execute aspectJTest

以上就是Aspecj的基本使用方法

總結

以上是生活随笔為你收集整理的框架:AspectJ的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。