Android AOP 實踐筆記

androidwing發表於2017-05-13

本文同步自wing的地方酒館

最近部落格更新越來越慢了,有兩方面原因:

1.沒啥好寫的。
2.應該沉下心好好沉澱自己,積累一些東西,部落格寫的太頻繁有”刷部落格“之嫌,還容易浮躁。
浮躁是大忌 ,所以還是沉下心好好學吧。

網上已經有了很多類似的文章,這裡再寫一次是為了自己當做筆記,主要是對APT,AspectJ、Javassist的簡單實用進行記錄,方便以後翻閱。

AOP是什麼這裡不多作解釋了,個人理解總結下來就是相對於各個垂直深入的業務邏輯,每個業務邏輯深度的某個層面他們有需要共同的特徵,此時對這種特徵進行統一的處理,也就是所謂的AOP(歡迎拍磚哈,技術在討論中提升)

主要應用場景:

  • 許可權檢查
  • 日誌記錄
  • 效能監控
  • 埋點操作

Android 下一些可以進行AOP的工具

APT

在編譯時生成 .java 檔案。

代表作品 ButterKnife 、 DataBinding、 EventBus3、Dagger2 等。

AspectJ

在.java編譯為.class的時候,進行程式碼注入。

代表作品: Hugo

Javassist

對已經編譯好的class檔案進行操作。

代表作品: 各類熱修復框架(為了解決類校驗問題)。

各個工具操作時機圖

這裡盜一張圖。原圖地址:www.jianshu.com/p/dca3e2c86…

Android AOP 實踐筆記

具體用法

APT

APT是編譯時生成程式碼的技術, 主要用到了註解 以及處理註解的Process
這裡我寫一個簡單的小例子,來展示如何使用APT,這個例子類似於MVPHelper的功能,但其實是沒有什麼亂用的,只是展示而已。

  • 建立一個module 用於宣告註解。

Android AOP 實踐筆記

這裡Contract註解,是為了標註一個Activity需要使用MVP模式。並且需要自動生成MVP程式碼。

Android AOP 實踐筆記

  • 再建立另一個module 用於處理這些註解。

Android AOP 實踐筆記

注意這裡必須是java庫,也就是說gradle要apply java 外掛,否則將引用不到javax包下的內容。

這個時候,我們只需要讓ConrtactProcessor 繼承 AbstractProcess,並且實現process函式去處理這個註解即可。
這裡生成程式碼使用了Javapoet, 我們的目標是在Activity上面使用@Contract註解自動生成MVP程式碼,並且@Inject自動注入presenter,如下圖:

Android AOP 實踐筆記

這些紅掉的程式碼,就是我們想要利用APT生成的程式碼,@Inject 用於表示注入mPresenter,這樣就不用我們自己new了,當然這裡是最簡單的注入展示。 我們反過來想想,想讓這些程式碼可以工作,生成的程式碼應該是怎樣的。生成的程式碼路徑如下所示:

Android AOP 實踐筆記

MVP部分的程式碼不多說,來說一說presenter是如何注入的,其實很簡單:

Android AOP 實踐筆記

結合上面紅色的程式碼看,應該會一目瞭然吧。

關於如何生成程式碼,只需要在process方法中使用javapoet即可,程式碼比較簡單繁瑣,這裡就不貼了,有需要的可以到文章尾部的連結檢視程式碼。

AspetJ

AspetJ的引入比較簡單,主要是滬江公司對AspetJ進行了一些Android方面的適配。

在gradle新增

classpath 'com.hujiang.aspectjx:gradle-android-plugin-aspectjx:1.0.10'複製程式碼

以及

apply plugin: 'android-aspectjx'複製程式碼

使用的時候,只需要新建一個類,並且使用@Aspect註解,即可對需要hook的類生效,並且無需直接使用。

因為在看這個之前有在用Xposed,所以感覺兩個很像,上手很快。

我們將要使用這個工具實現Activity 啟動時間的監控,以及登入許可權管理的注入,以往判斷使用者登入往往需要每個函式都判斷一下最後執行邏輯,其實這完全可以注入進去,就像”切面“所說,需要登入的地方,一刀切。

實現Activity啟動時間監控,這裡寫簡單一點,單純的從onCreate開始到onResume結束進行計時操作。

Android AOP 實踐筆記

另外一個是登入檢驗操作,我們理想的事情是給一個函式新增一個註解,並且這個註解來判斷是否登入執行相應的轉跳提示操作。

示意如下,比如onResume需要判斷是否登入,只需要一個註解

Android AOP 實踐筆記

我們把需要的邏輯判斷寫在@AspetJ 註解的類裡即可。

Android AOP 實踐筆記

這樣不管是埋點還是效能監控還是登入許可權檢驗,都可以異常方便的執行。再也不像原先那樣麻煩了。

Javassist

這個需要結合自定義gradle plugin一起操作,大家都知道apk編譯的時候,先把java編譯為class檔案,接下來會變為dex檔案,gradle提供了transform api,可以讓我們class變為dex之前做任何想做的事情。

首先建立一個buildSrc的module,這裡面建立的類都是groovy的類,所以副檔名要寫groovy。至於內容嘛。。因為相容java 隨便你咯-。-

建立一個Plugin,叫做Regsiter, 只需要讓他implement Plugin 外掛即可, 此時重寫apply方法,就可以在主工程中apply這個外掛。

另外我們需要結合transform, 所以要給android外掛註冊一下transform

Android AOP 實踐筆記

在transform裡,我們就可以對所有檔案進行操作了

Android AOP 實踐筆記

ClassInjector 主要是使用Javassist進行對class檔案的改變操作。

Android AOP 實踐筆記

值得注意的是,如果操作的過程中需要使用android sdk內容,需要手動將 android.jar新增到 ClassPool裡面。否則會提示找不到類的情況。

本文涉及Demo程式碼地址
github.com/githubwing/…

歡迎加入Android地方酒館(425983695)一起研究Android技術。

參考文章

1.www.jianshu.com/p/dca3e2c86…
2.blog.csdn.net/eclipsexys/…
3.blog.csdn.net/u010386612/…

相關文章