Android Studio中AspectJ的簡單使用一(自定義PointCut)
使用自定義註解的方式,步驟如下
1.建立自定義註解;
2.建立操作類(切入檔案);
3.呼叫註解。
一、建立自定義註解。
程式碼如下。
package cm.richeninfo.com.astestaspect20180309.annotation; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** * Created by wangxiaowu on 2018/3/9 14:08 * decribe * 註解類 */ @Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) public @interface BehaviorTrace { String value(); }
注意:
@Target、@Retention、@interface
備註:
java中元註解有四個: @Retention @Target @Document @Inherited;
@Retention:註解的保留位置
@Retention(RetentionPolicy.SOURCE) //註解僅存在於原始碼中,在class位元組碼檔案中不包含
@Retention(RetentionPolicy.CLASS) // 預設的保留策略,註解會在class位元組碼檔案中存在,但執行時無法獲得,
@Retention(RetentionPolicy.RUNTIME) // 註解會在class位元組碼檔案中存在,在執行時可以通過反射獲取到
@Target:註解的作用目標
@Target(ElementType.TYPE) //介面、類、列舉、註解
@Target(ElementType.FIELD) //欄位、列舉的常量
@Target(ElementType.METHOD) //方法
@Target(ElementType.PARAMETER) //方法引數
@Target(ElementType.CONSTRUCTOR) //建構函式
@Target(ElementType.LOCAL_VARIABLE)//區域性變數
@Target(ElementType.ANNOTATION_TYPE)//註解
@Target(ElementType.PACKAGE) ///包
@Document:說明該註解將被包含在javadoc中
@Inherited:說明子類可以繼承父類中的該註解
RetentionPolicy.SOURCE:註解只保留在原始檔,當Java檔案編譯成class檔案的時候,註解被遺棄;
RetentionPolicy.CLASS:註解被保留到class檔案,但jvm載入class檔案時候被遺棄,這是預設的生命週期;
RetentionPolicy.RUNTIME:註解不僅被儲存到class檔案中,jvm載入class檔案之後,仍然存在;
二、建立操作類
程式碼如下。
package cm.richeninfo.com.astestaspect20180309.aspect; import android.util.Log; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.After; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; import org.aspectj.lang.annotation.Pointcut; import org.aspectj.lang.annotation.RequiredTypes; import org.aspectj.lang.reflect.MethodSignature; import java.util.Objects; import cm.richeninfo.com.astestaspect20180309.annotation.BehaviorTrace; /** * Created by wangxiaowu on 2018/3/9 14:36 * decribe */ @Aspect public class BehaviorTraceAspect { //關聯的註解類cm.richeninfo.com.astestaspect20180309.annotation.BehaviorTrace @Pointcut("execution(@cm.richeninfo.com.astestaspect20180309.annotation.BehaviorTrace * *(..))") public void methodAnnotatedWithBehaviorTraceAspect(){ //下面的程式碼沒有執行 Log.d("system.out","methodAnnotated**********************"); } // @Before("methodAnnotatedWithBehaviorTraceAspect()") // public void beforeMethod() throws Throwable{ // Log.v("system.out","before method is executed"); // } // // @After("methodAnnotatedWithBehaviorTraceAspect()") // public void afterMethod() throws Throwable{ // Log.v("system.out","after method is executed"); // } //關聯的操作methodAnnotatedWithBehaviorTraceAspect() @Around("methodAnnotatedWithBehaviorTraceAspect()") public Object aroundMethod(ProceedingJoinPoint joinPoint) throws Throwable{ Object result=null; if(null!=joinPoint){ MethodSignature methodSignature=(MethodSignature)joinPoint.getSignature(); String className=methodSignature.getDeclaringType().getSimpleName(); String methodName=methodSignature.getName(); String funName=methodSignature.getMethod().getAnnotation(BehaviorTrace.class).value(); Log.d("system.out","arround method is executed.before"); //統計時間 long begin=System.currentTimeMillis(); result=joinPoint.proceed(); long duration=System.currentTimeMillis()-begin; Log.d("system.out",String.format("around method is executed .after 功能:%s,%s類的%s方法執行了,用時%d ms",funName,className,methodName,duration)); return result; } return result; } }
注意:
類必須要加上@Aspect註解。再宣告一個方法作為切點,這個方法需要加上註解:
@pointcut(execution(@全類名 * *(. .))) 後面的兩個表示*匹配所有的方法名,兩個.表示匹配所有的方法引數
備註:
AspectJ的切入點表示式中,可以用execution、call。
對於Call來說:
Call(Before) Pointcut{ Pointcut Method } Call(After) 對於Execution來說: Pointcut{ execution(Before) Pointcut Method execution(After) }三、呼叫註解
程式碼如下。
package cm.richeninfo.com.astestaspect20180309; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.util.Log; import android.view.View; import cm.richeninfo.com.astestaspect20180309.annotation.BehaviorTrace; public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); findViewById(R.id.activity_main_tv1).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { testAspect(); } }); } @BehaviorTrace("測試 aspect") private int testAspect(){ Log.v("system.out","testAspect inner is executed"); return 100; } }