AspectJ是一個面向切面編程的一個框架,它擴展了java語言,並定義了實現AOP的語法。在將.java文件編譯爲.class文件時默認使用javac編譯工具,AspectJ會有一套符合java字節碼編碼規範的編譯工具來替代javac,在將.java文件編譯爲.class文件時,會動態的插入一些代碼來作到對某一類特定東西的統一處理。經過預編譯方式和運行期動態代理實如今不修改源代碼的狀況下給程序動態統一添加功能的技術。對業務邏輯的各個部分進行隔離,耦合度下降,提升程序的可重用性,同時提升了開發的效率。java
OOP(面向對象編程)針對業務處理過程的實體及其屬性和行爲進行抽象封裝,以得到更加清晰高效的邏輯單元劃分,而AOP則是針對業務處理過程當中的切面進行提取,它所面對的是處理過程當中的某個步驟或階段,以得到邏輯過程當中各部分之間低耦合性的隔離效果。
AOP編程的主要用途有:日誌記錄,行爲統計,安全控制,事務處理,異常處理,系通通一的認證、權限管理等。
AspectJ的配置很麻煩,這裏使用 AspectJX 框架,框架地址:https://github.com/HujiangTechnology/gradle_plugin_android_aspectjxandroid
首先,先來點軟柿子捏捏,體驗一把什麼叫切面編程,比較經常使用的埋點統計,在咱們須要本身去實現埋點統計的時候,不少人是否是寫個埋點工具類,而後在每一個入口的地方去添加埋點的方法,若是埋點較多會感受很煩,若是用AspectJ怎麼去實現呢,拋開業務邏輯,一切從簡git
首先添加依賴
接着定義一個測試方法,testAspect,這個方法就是觸發點,只要我調用了這個方法,就統計一下
而後就開始編寫咱們的AspectUtils類了,這個類須要用 @Aspect 聲明爲標記類github
而後在標識類下面寫切面方法編程
這些是什麼意思呢,此處須要一段註釋安全
/**
@Pointcut("execution(" +//執行語句
"@com.kotlinstrong.utils.aspect.MyAnnotationOnclick" +//註解篩選
"*" + //類路徑,*爲任意路徑
"*" + //方法名,*爲任意方法名
"(..)" +//方法參數,'..'爲任意個任意類型參數
")" +
" && " +//並集
)
@Aspect:聲明切面,標記類
@Pointcut(切點表達式):定義切點,標記方法
@Before(切點表達式):前置通知,切點以前執行
@Around(切點表達式):環繞通知,切點先後執行
@After(切點表達式):後置通知,切點以後執行
@AfterReturning(切點表達式):返回通知,切點方法返回結果以後執行
@AfterThrowing(切點表達式):異常通知,切點拋出異常時執行
* */
能夠看到,咱們寫的測試方法是test開頭的,before是在方法執行前切入,在onCreate裏面調用方法,在運行程序後,打印出方法名稱
是否是很敢單,可是假如我要根據方法的返回值來添加邏輯定義埋點呢?腫木辦,不要慌,這都不是事,再寫一個測試方法,返回一個數值app
在工具類裏面須要加一個方法,從上面的註釋能夠看到,須要返回值的,用 @AfterReturning,看圖說話框架
在註解的後面定義了一個返回參數id,這裏要注意,註解上的returning標註的參數名稱要跟下面申明的參數名稱一致函數
而後仍是同樣的打印出信息,運行一下看看工具
打印出1,完美,這樣埋點是否是方便多了,只要在你須要執行的方法出匹配就能自動切入埋點,自成一類,是否是感受很興奮,原來如此簡單,可是沒結束,上面講到了埋點,還能有什麼比較常規的
操做嗎。
確定有的,根據方法名稱匹配切入有時候可能會修改方法名什麼的,在一些場合確定也不合適,這裏能夠自定義註解去解決,恰好咱們平時跳轉頁面會作一個比較頻繁的操做,防抖,這裏來實現一個防抖效果,加載一個列表,添加item點擊事件,點擊後跳轉詳情頁,若是你快速點擊,會進入屢次,這顯然不是咱們想要的效果,那麼咱們能夠自定義一個註解,而後在跳轉的方法上添加註解,在切面類編寫防抖觸發,點擊間隔設置爲1000毫秒
/* 防抖點擊 */
/**
* SOURCE:運行時 不存儲在編譯後的 Class 文件。
* BINARY:加載時 存儲在編譯後的 Class 文件,可是反射不可見。
* RUNTIME:編譯時 存儲在編譯後的 Class 文件,反射可見。
*/
@Retention(AnnotationRetention.RUNTIME)
/**
* CLASS:類,接口或對象,註解類也包括在內。
* ANNOTATION_CLASS:只有註解類。
* TYPE_PARAMETER:Generic type parameter (unsupported yet)通用類型參數(還不支持)。
* PROPERTY:屬性。
* FIELD:字段,包括屬性的支持字段。
* LOCAL_VARIABLE:局部變量。
* VALUE_PARAMETER:函數或構造函數的值參數。
* CONSTRUCTOR:僅構造函數(主函數或者第二函數)。
* FUNCTION:方法(不包括構造函數)。
* PROPERTY_GETTER:只有屬性的 getter。
* PROPERTY_SETTER:只有屬性的 setter。
* TYPE:類型使用。
* EXPRESSION:任何表達式。
* FILE:文件。
* TYPEALIAS:@SinceKotlin("1.1") 類型別名,Kotlin1.1已可用。
*/
@Target(AnnotationTarget.FUNCTION)
annotation class MyAnnotationOnclick(
/** 點擊間隔時間 */
val value: Long = 1000
)
這裏一個註解類就完成了,而後在編寫一個測試方法,在方法裏去跳轉一個頁面,而後在你的點擊事件裏調用這個跳轉方法
接下來到咱們的切面類去定義一個切點
這裏識別註解標識的方法,告訴代碼注入工具,在何處注入一段特定帶條件的代碼的表達式,此處的條件就是咱們定義的註解,而後在編寫咱們的切入方法
此處獲匹配到註解方法,而後調用了一個ClickUtils類去作防抖操做
運行你的程序發現,快速點擊的時候只會觸發一次了,只須要在你操做的跳轉方法裏添加一個註解就能夠達到防抖效果,nice,扶我起來,我還能學
說到切面編程就不得不說登陸了,通常app就是兩種方式,先登陸在進入,先進入,在檢查讓你登陸,那麼若是是先進入瀏覽,而後在檢測讓用戶登陸是否是也須要在多個地方去判斷呢,這裏是否是也同樣,能夠用Aspect去作呢,拿起鍵盤就是一頓ctrl+c
仍是同樣的套路,首先定義一個註解
而後我須要在打開詳情頁的時候去檢測,若是沒有登陸的話就直接跳轉到登陸頁面去
在到工具類裏寫切面表達式跟方法,這裏用最簡單的方式來實現效果,真的登陸確定不會這麼簡單
運行後,點擊詳情,會發現打開了一個詳情後再次打開了一個登陸頁面,這裏複用也是很方便
不行了,學不動了,趕忙掐人中
Aspects不是萬能的,可是有了它能夠對咱們的開發帶來極大的方便,這裏附上Kotlin項目地址,喜歡的請star