介紹:
AspectJ是一個面向切面編程的一個框架,它擴展了java語言,并定義了實現(xiàn)AOP的語法。在將.java文件編譯為.class文件時默認使用javac編譯工具,AspectJ會有一套符合java字節(jié)碼編碼規(guī)范的編譯工具來替代javac,在將.java文件編譯為.class文件時,會動態(tài)的插入一些代碼來做到對某一類特定東西的統(tǒng)一處理。通過預編譯方式和運行期動態(tài)代理實現(xiàn)在不修改源代碼的情況下給程序動態(tài)統(tǒng)一添加功能的技術。對業(yè)務邏輯的各個部分進行隔離,耦合度降低,提高程序的可重用性,同時提高了開發(fā)的效率。
OOP(面向?qū)ο缶幊蹋┽槍I(yè)務處理過程的實體及其屬性和行為進行抽象封裝,以獲得更加清晰高效的邏輯單元劃分,而AOP則是針對業(yè)務處理過程中的切面進行提取,它所面對的是處理過程中的某個步驟或階段,以獲得邏輯過程中各部分之間低耦合性的隔離效果。
AOP編程的主要用途有:日志記錄,行為統(tǒng)計,安全控制,事務處理,異常處理,系統(tǒng)統(tǒng)一的認證、權限管理等。
AspectJ的配置很麻煩,這里使用 AspectJX 框架,框架地址:https://github.com/HujiangTechnology/gradle_plugin_android_aspectjx
不過kotlin高版本中如果使用AspectJX 有很大部分人會遇到包沖突問題,就是 zip is empty,在我的項目里介紹過了,就不多說了,地址在文章末尾
首先,先來點軟柿子捏捏,體驗一把什么叫切面編程,比較常用的埋點統(tǒng)計,在我們需要自己去實現(xiàn)埋點統(tǒng)計的時候,很多人是不是寫個埋點工具類,然后在每個入口的地方去添加埋點的方法,如果埋點較多會感覺很煩,如果用AspectJ怎么去實現(xiàn)呢,拋開業(yè)務邏輯,一切從簡
首先添加依賴

![]()

接著定義一個測試方法,testAspect,這個方法就是觸發(fā)點,只要我調(diào)用了這個方法,就統(tǒng)計一下

然后就開始編寫我們的AspectUtils類了,這個類需要用 @Aspect 聲明為標記類

然后在標識類下面寫切面方法

這些是什么意思呢,此處需要一段注釋
/**
@Pointcut("execution(" +//執(zhí)行語句
"@com.kotlinstrong.utils.aspect.MyAnnotationOnclick" +//注解篩選
"*" + //類路徑,*為任意路徑
"*" + //方法名,*為任意方法名
"(..)" +//方法參數(shù),'..'為任意個任意類型參數(shù)
")" +
" && " +//并集
)
@Aspect:聲明切面,標記類
@Pointcut(切點表達式):定義切點,標記方法
@Before(切點表達式):前置通知,切點之前執(zhí)行
@Around(切點表達式):環(huán)繞通知,切點前后執(zhí)行
@After(切點表達式):后置通知,切點之后執(zhí)行
@AfterReturning(切點表達式):返回通知,切點方法返回結(jié)果之后執(zhí)行
@AfterThrowing(切點表達式):異常通知,切點拋出異常時執(zhí)行
* */
可以看到,我們寫的測試方法是test開頭的,before是在方法執(zhí)行前切入,在onCreate里面調(diào)用方法,在運行程序后,打印出方法名稱

是不是很敢單,但是假如我要根據(jù)方法的返回值來添加邏輯定義埋點呢?腫木辦,不要慌,這都不是事,再寫一個測試方法,返回一個數(shù)值

在工具類里面需要加一個方法,從上面的注釋可以看到,需要返回值的,用 @AfterReturning,看圖說話

在注解的后面定義了一個返回參數(shù)id,這里要注意,注解上的returning標注的參數(shù)名稱要跟下面申明的參數(shù)名稱一致
然后還是一樣的打印出信息,運行一下看看

打印出1,完美,這樣埋點是不是方便多了,只要在你需要執(zhí)行的方法出匹配就能自動切入埋點,自成一類,是不是感覺很興奮,原來如此簡單,但是沒結(jié)束,上面講到了埋點,還能有什么比較常規(guī)的
操作嗎。
肯定有的,根據(jù)方法名稱匹配切入有時候可能會修改方法名什么的,在一些場合肯定也不合適,這里可以自定義注解去解決,剛好我們平時跳轉(zhuǎn)頁面會做一個比較頻繁的操作,防抖,這里來實現(xiàn)一個防抖效果,加載一個列表,添加item點擊事件,點擊后跳轉(zhuǎn)詳情頁,如果你快速點擊,會進入多次,這顯然不是我們想要的效果,那么我們可以自定義一個注解,然后在跳轉(zhuǎn)的方法上添加注解,在切面類編寫防抖觸發(fā),點擊間隔設置為1000毫秒
/* 防抖點擊 */
/**
* SOURCE:運行時 不存儲在編譯后的 Class 文件。
* BINARY:加載時 存儲在編譯后的 Class 文件,但是反射不可見。
* RUNTIME:編譯時 存儲在編譯后的 Class 文件,反射可見。
*/
@Retention(AnnotationRetention.RUNTIME)
/**
* CLASS:類,接口或?qū)ο螅⒔忸愐舶ㄔ趦?nèi)。
* ANNOTATION_CLASS:只有注解類。
* TYPE_PARAMETER:Generic type parameter (unsupported yet)通用類型參數(shù)(還不支持)。
* PROPERTY:屬性。
* FIELD:字段,包括屬性的支持字段。
* LOCAL_VARIABLE:局部變量。
* VALUE_PARAMETER:函數(shù)或構(gòu)造函數(shù)的值參數(shù)。
* CONSTRUCTOR:僅構(gòu)造函數(shù)(主函數(shù)或者第二函數(shù))。
* FUNCTION:方法(不包括構(gòu)造函數(shù))。
* 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
)
這里一個注解類就完成了,然后在編寫一個測試方法,在方法里去跳轉(zhuǎn)一個頁面,然后在你的點擊事件里調(diào)用這個跳轉(zhuǎn)方法

接下來到我們的切面類去定義一個切點

這里識別注解標識的方法,告訴代碼注入工具,在何處注入一段特定帶條件的代碼的表達式,此處的條件就是我們定義的注解,然后在編寫我們的切入方法

此處獲匹配到注解方法,然后調(diào)用了一個ClickUtils類去做防抖操作

運行你的程序發(fā)現(xiàn),快速點擊的時候只會觸發(fā)一次了,只需要在你操作的跳轉(zhuǎn)方法里添加一個注解就可以達到防抖效果,nice,扶我起來,我還能學
說到切面編程就不得不說登錄了,一般app就是兩種方式,先登錄在進入,先進入,在檢查讓你登錄,那么如果是先進入瀏覽,然后在檢測讓用戶登錄是不是也需要在多個地方去判斷呢,這里是不是也一樣,可以用Aspect去做呢,拿起鍵盤就是一頓ctrl+c
還是一樣的套路,首先定義一個注解

然后我需要在打開詳情頁的時候去檢測,如果沒有登錄的話就直接跳轉(zhuǎn)到登錄頁面去

在到工具類里寫切面表達式跟方法,這里用最簡單的方式來實現(xiàn)效果,真的登錄肯定不會這么簡單

運行后,點擊詳情,會發(fā)現(xiàn)打開了一個詳情后再次打開了一個登錄頁面,這里復用也是很方便,當然,它還有很多作用,比如計算方法的耗時等等
Aspects不是萬能的,但是有了它可以對我們的開發(fā)帶來極大的方便,這里附上Kotlin項目地址,從未停止更新,如果對你有幫助,star關注一下吧
浙公網(wǎng)安備 33010602011771號