1. 程式人生 > >AspectJ自定義註解之埋點(三)

AspectJ自定義註解之埋點(三)

介紹

埋點,我們公司有很多核心的方法,要給大資料做統計需要做埋點,埋點其實就是將使用者操作這部分業務邏輯的記錄下來,給大資料作分析,前端埋點就是插入上報資訊的功能,後端埋點一般是Api埋點,埋點程式碼和業務邏輯沒有任何關係,如果入侵是寫入(手動插入埋點程式碼),將來的維護成本大大提升,更何況埋所有的點選事件呢?工作量很大,所以AspectJ做埋點在合適不過了

onClick事件埋點

這還不簡單?晒程式碼

     findViewById(R.id.btn_test).setOnClickListener(new View.OnClickListener() {
            @Override
public void onClick(View v) { ToastUtil.getInstance().showToast(getApplicationContext(), "點選事件發生點選"); } });
    @Before("execution(* android.view.View.OnClickListener.onClick(android.view.View))")
    public void hookOnClicknPoint(JoinPoint joinPoint)
{ Log.d("wyz", "點選事件"); }

自定義埋點

自定義埋點,也就是如果我想對此方法進行埋點,我只需要新增物件的自定義的註解,然後就會注入埋點邏輯

什麼是註解

對於很多初次接觸的開發者來說應該都有這個疑問?Annontation是Java5開始引入的新特徵,中文名稱叫註解。它提供了一種安全的類似註釋的機制,用來將任何的資訊或元資料(metadata)與程式元素(類、方法、成員變數等)進行關聯。為程式的元素(類、方法、成員變數)加上更直觀更明瞭的說明,這些說明資訊是與程式的業務邏輯無關,並且供指定的工具或框架使用。Annontation像一種修飾符一樣,應用於包、型別、構造方法、方法、成員變數、引數及本地變數的宣告語句中。   Java註解是附加在程式碼中的一些元資訊,用於一些工具在編譯、執行時進行解析和使用,起到說明、配置的功能。註解不會也不能影響程式碼的實際邏輯,僅僅起到輔助性的作用。包含在 java.lang.annotation 包中。

元註解

java.lang.annotation提供了四種元註解,專門註解其他的註解(在自定義註解的時候,需要使用到元註解):

暱稱 解釋
@Documented 註解是否將包含在JavaDoc中
@Retention 定義該註解的生命週期,RetentionPolicy引數包括
@Target 表示該註解用於什麼地方。預設值為任何元素,表示該註解用於什麼地方。可用的ElementType引數包括
@Inherited 是否允許子類繼承該註解
Retention型別 介紹
RetentionPolicy.SOURCE 在編譯階段丟棄。這些註解在編譯結束之後就不再有任何意義,所以它們不會寫入位元組碼。@Override, @SuppressWarnings都屬於這類註解。
RetentionPolicy.CLASS 在類載入的時候丟棄。在位元組碼檔案的處理中有用。註解預設使用這種方式
RetentionPolicy.RUNTIME 始終不會丟棄,執行期也保留該註解,因此可以使用反射機制讀取該註解的資訊。我們自定義的註解通常使用這種方式
ElementType型別 介紹
ElementType.CONSTRUCTOR 用於描述構造器
ElementType.FIELD 成員變數、物件、屬性(包括enum例項)
ElementType.LOCAL_VARIABLE 用於描述區域性變數
ElementType.METHOD 用於描述方法
ElementType.PACKAGE 用於描述包
ElementType.PARAMETER 用於描述引數
ElementType.TYPE 用於描述類、介面(包括註解型別) 或enum宣告

定義註解

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation {
    int id();
    String description() default "我是預設描述";
}

這裡說下,剛開始的時候,我考過,這個註解定義在哪裡合適呢?我一開始寫在了主專案中,最後發現不合適,需要定義在AspectJ的libray中比較合適

編寫AspectJ程式碼

    /**
     * 自定義註解埋點
     */
    @Before("execution(@com.mmvoice.aspectj.anantation.MyAnnotation * *(..))")
    public void buriedPoint(JoinPoint joinPoint) {
        // 獲取註解
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        // 這也就是為何我要將MyAnnotation定義到,library中了,這類要使用
        MyAnnotation annotation = signature.getMethod().getAnnotation(MyAnnotation.class);
        Log.d("wyz", "埋點邏輯執行-資料-" + annotation.id() + " " + annotation.description());
    }

可以看到編寫過濾條件的時候,註解簽名寫了一個@

表示式 描述
註解切入點表示式 advice (@Annotation 訪問訪問 返回型別 切入點路徑)
路徑切入點表示式 advice( 訪問訪問 返回型別 切入點路徑)