欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

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

 更新時(shí)間:2018年04月20日 10:21:34   作者:Cavalier-  
這篇文章主要介紹了在Android項(xiàng)目中使用AspectJ的方法,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧

什么是AOP

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

AspectJ

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

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

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

接入說(shuō)明

請(qǐng)自行查看開(kāi)源項(xiàng)目中的接入配置過(guò)程

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 說(shuō)明 實(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-initialization Object在構(gòu)造函數(shù)中做的一些工作。 -
initialization Object在構(gòu)造函數(shù)中做的工作。 -
static initialization 類初始化 比如類的static{}
handler 異常處理 比如try catch 中,對(duì)應(yīng)catch內(nèi)的執(zhí)行
advice execution 這個(gè)是AspectJ 的內(nèi)容 -

Pointcuts 介紹

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

Advice

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

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

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

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

Before 和 After 其實(shí)還是很好理解的,也就是在Pointcuts之前和之后,插入代碼,那么Android呢,從字面含義上來(lái)講,也就是在方法前后各插入代碼,他包含了 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();

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

@DebugTrace
public 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,那么這兩種語(yǔ)法有什么區(qū)別呢?對(duì)call來(lái)說(shuō):

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

對(duì)Execution來(lái)說(shuō):

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

Withincode

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

public class MainActivity extends AppCompatActivity{
final String TAG = MainActivity.class.getSimpleName();

@Orveride
protected 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組合的方式,來(lái)精確定位切入點(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 語(yǔ)法

execution()是最常用的切點(diǎn)函數(shù),其語(yǔ)法如下所示:

例如下面這段語(yǔ)法:@Around(“execution(* *..MainActivity+.on*(..))")

整個(gè)表達(dá)式可以分為五個(gè)部分:
1.execution()是表達(dá)式主體
2.第一個(gè)*號(hào)代表返回類型,*號(hào)代表所有的類型。
3.包名 表示需要攔截的包名,這里使用*.代表匹配所有的包名。
4.第二個(gè)*號(hào)表示類名,后面跟.MainActivity是指具體的類名叫MainActivity。
5.*(..) 最后這個(gè)星號(hào)表示方法名,+.代表具體的函數(shù)名,*號(hào)通配符,包括括弧號(hào)里面表示方法的參數(shù),兩個(gè)dot代表任意參數(shù)。

遇到的錯(cuò)誤

1.以下錯(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

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

最新評(píng)論