Android監測用戶行為之中AOP編程之AspectJ實戰
前言介紹
Android中的AOP編程之AspectJ實戰
人與宇宙的關係的博客地址:
正文
文章背景
最近在給某某銀行做項目的時,涉及到了數據埋點,性能監控等問題,那我們起先想到的有兩種方案:
這種方案看上去似乎可行,但有弊端,不僅會給程序員增加巨大工作量、而且最致命的是會嚴重拖累整個APP的性能。
方案之一就是藉助第三方,比如友盟、Bugly等,由於項目是部署在銀行的網路框架之內的,所以該方案不可行。
另外一種方案是就是給每一個方法裡面數據打點,然後寫入SD卡,定時上報給自己的伺服器,伺服器來進行統計分析
好多都應無奈之舉放棄了該需求,但數據埋點實現用戶行為的收集分析和性能監控對於技術部和運營部來說是一件非常有價值的事情,所以作為程序的我必應尋找解決方案
慶幸的是我們除了OOP編程思想外,還有一種編程思想就是AOP編程,這種編程思想能解決此類問題。
文章目標
實現用戶行為採集
實現方法性能監控
探討AOP編程實戰
看圖簡單解讀Android的AOP實戰
看到沒有,在LinearLayoutTestActivity中除了載入布局的操作外,我並沒有干其他的什麼,但當我點擊菜單跳轉到該Activity時,onCreate的方法和參數被列印出來,甚至LinearLayoutTestActivity類信息也被列印出來了,干這個事情的是TraceAspect這個類。到這裡上面所說的用戶的行為跟蹤就輕而易舉得以實現,那麼下面我們開始來了解一下這種技術。
什麼是AOP
面向切面編程(AOP,Aspect-oriented programming)需要把程序邏輯分解成『關注點』(concerns,功能的內聚區域)。
這意味著,在 AOP 中,我們不需要顯式的修改就可以向代碼中添加可執行的代碼塊。這種編程範式假定『橫切關注點』(cross-cutting concerns,多處代碼中需要的邏輯,但沒有一個單獨的類來實現)應該只被實現一次,且能夠多次注入到需要該邏輯的地方。
代碼注入是 AOP 中的重要部分:它在處理上述提及的橫切整個應用的『關注點』時很有用,例如日誌或者性能監控。這種方式,並不如你所想的應用甚少,相反的,每個程序員都可以有使用這種注入代碼能力的場景,這樣可以避免很多痛苦和無奈。
AOP 是一種已經存在了很多年的編程範式。我發現把它應用到 Android 開發中也很有用。經過一番調研後,我認為我們用它可以獲得很多好處和有用的東西。
AspectJ是什麼
AspectJ實際上是對AOP編程思想的一個實踐,它不是一個新的語言,它就是一個代碼編譯器(ajc)
在Java編譯器的基礎上增加了一些它自己的關鍵字識別和編譯方法。因此,ajc也可以編譯Java代碼。
它在編譯期將開發者編寫的Aspect程序編織到目標程序中,對目標程序作了重構,目的就是建立目標程序與Aspect程序的連接(耦合,獲得對方的引用(獲得的是聲明類型,不是運行時類型)和上下文信息),從而達到AOP的目的(這裡在編譯期還是修改了原來程序的代碼,但是是ajc替我們做的)。
當然,除了AspectJ以外,還有很多其它的AOP實現,例如XPosed、DexPosed、ASMDex。
為什麼用 AspectJ?
功能強大:它就是一個編譯器+一個庫,可以讓開發者最大限度的發揮,實現形形色色的AOP程序!
非侵入式監控: 可以在不修監控目標的情況下監控其運行,截獲某類方法,甚至可以修改其參數和運行軌跡!
支持編譯期和載入時代碼注入,不影響性能。
易用易學:它就是Java,只要會Java就可以用它。
如何Android項目中使用AspectJ
使用方法有兩種:
插件的方式:網上有人在github上提供了集成的插件gradle-android-aspectj-plugin。這種方式配置簡單方便,但經測試無法兼容databinding框架,這個問題現在作者依然沒有解決,希望作者能夠快速解決。
Gradle配置的方式:配置有點麻煩,不過國外一個大牛在build文件中添加了一些腳本,雖然有點難懂,但可以在AS中使用。文章出處:https://fernandocejas.com/2014/08/03/aspect-oriented-programming-in-android/
Step
1、創建一個AS原工程
2、再創建一個module(Android Library)
3、在gintonic中添加AspectJ依賴,同時編寫build腳本,添加任務,使得IDE使用ajc作為編譯器編譯代碼,然後把該Module添加至主工程Module中。
4、在主build.gradle(Module:app)中添加也要添加AspectJ依賴,同時編寫build腳本,添加任務,目的就是為了建立兩者的通信,使得IDE使用ajc編譯代碼。
5、在Module(gintonic)中新建一個名為」TraceAspect」類
6、LinearLayoutTestActivity類
然後運行我們的程序看日誌列印效果
上面的代碼片段中有兩處地方值得注意,一個是把這個類註解為@Aspect,另一個是給方法的的註解並加上了類似正則表達式的過濾條件,我們先按照我的步驟走,後面會一一講解。
根據圖片我們會驚奇的發現LinearLayoutTestActivity中的onCreate(Bundle savedInstanceState)方法被TraceAspect類赤裸裸的監控了,不僅截取到了LinearLayoutTestActivity類信息和方法及方法參數。
那這到底是怎麼回事呢?我們可以使用反編譯我的apk看一下相關的代碼
我們可以發現,在onCreate執行之前,插入了一些AspectJ的代碼,並且調用了TraceAspect中的 onActivityMethodBefore(JoinPoint joinPoint)方法。這個就是AspectJ的主要功能,拋開AOP的思想來說,我們想做的,實際上就是『在不侵入原有代碼的基礎上,增加新的代碼』。
監控Activity的下其它被調用的方法
看到沒有我們僅僅在TraceAspect類中編寫一個方法就可以監控RelativeLayoutTestActivity中被用戶點擊的方法,這樣就可以輕輕鬆鬆採集用戶行
代碼:
我們還是照樣看來看一下反編譯的代碼 這是在RelativeLayoutTestActivity類中調用testAOP()我們的源碼:
下面是反編譯的代碼,讀者只要關注testAOP()方法即可
我們不難發現我們的代碼輕鬆被AspectJ重構了,而且這種重構是在不修改原有代碼的情況下無縫的被插入。
Fragment的中的方法監控
上面我已經演示過Activity中的方法強勢插入,在Fragment中依然可行
AspectJ原理剖析
1、Join Points(連接點) Join Points,簡稱JPoints,是AspectJ的核心思想之一,它就像一把刀,把程序的整個執行過程切成了一段段不同的部分。例如,構造方法調用、調用方法、方法執行、異常等等,這些都是Join Points,實際上,也就是你想把新的代碼插在程序的哪個地方,是插在構造方法中,還是插在某個方法調用前,或者是插在某個方法中,這個地方就是Join Points,當然,不是所有地方都能給你插的,只有能插的地方,才叫Join Points。
2、Pointcuts(切入點) 告訴代碼注入工具,在何處注入一段特定代碼的表達式。例如,在哪些 joint points 應用一個特定的 Advice。切入點可以選擇唯一一個,比如執行某一個方法,也可以有多個選擇,可簡單理解為帶條件的Join Points,作為我們需要的代碼切入點。
3、Advice(通知) 如何注入到我的class文件中的代碼。典型的 Advice 類型有 before、after 和 around,分別表示在目標方法執行之前、執行後和完全替代目標方法執行的代碼。 上面的例子中用的就是最簡單的Advice——Before。
4、Aspect(切面): Pointcut 和 Advice 的組合看做切面。例如,我們在應用中通過定義一個 pointcut 和給定恰當的advice,添加一個日誌切面。
5、Weaving(織入): 注入代碼(advices)到目標位置(joint points)的過程。 由於微信對篇幅大小的限制,這裡只是關於部分AOP的部分講解。 更多參考:http://blog.csdn.net/xinanheishao/article/details/74082605
注意這裡
AOP 應用場景非常多。 只要在我們想監控的方法上加上 @DebugTrace即可,我在這裡給onMeasure方法上註解,當我進入LinearLayoutTestActivity 類時,運行如下:
博客地址:
最後附上Dome下載地址:
http://download.csdn.net/download/xinanheishao/9886917
提供一個反編譯工具:
終端研發部提倡:沒有做不到的,只有想不到的。
在這裡獲得的不僅僅是技術!
讓心,在陽光下學會舞蹈
讓靈魂,在痛苦中學會微笑
—終端研發部—
這裡學到的不僅僅是技術
TAG:終端研發部 |
※使用 VS Code 進行 Python 編程
※並發編程之AQS(AbstractQueuedSynchronizer)
※Perl Socket 編程
※TensorFlow Probability 概率編程入門級實操教程
※JSP 編程Session
※jQuery UI編程的 ThemeRoller
※Web Pages 編程 PHP
※Docker編程 Hello World
※Scala 編程Collection
※WebPages編程C和VB實例
※Python中的IO編程
※ASP.NET Web Forms 編程
※ionic 編程Range
※XPath編程 Examples
※jQuery Mobile編程
※XLink 和 XPointer 編程
※育碧攜手Mozilla 合作開發AI編程助手Clever-Commit
※React 編程的Refs
※基於Swift 5的編程教學Swift Playgrounds即將推出
※Python非同步Web編程