因為項目和團(tuán)隊的需要,個人開始對插件化技術(shù)預(yù)研?,F(xiàn)在這個技術(shù)已經(jīng)在Android開發(fā)領(lǐng)域變得相當(dāng)?shù)幕馃幔蟾艔?014年開始已經(jīng)有很多優(yōu)秀的流派產(chǎn)生,到最近的滴滴插件化項目的開源,目前插件化技術(shù)越來越成熟。對大型項目從架構(gòu)到實施都是一種優(yōu)秀的解決方案。閑話不多說,從基數(shù)到深入在學(xué)習(xí)過程中所需的各方面的知識點在此都一一做個整理。
插件化開發(fā)的優(yōu)勢
1、大型項目業(yè)務(wù)繁雜,需要多個部門協(xié)同合作。人多則亂,所以需要合適的架構(gòu)對業(yè)務(wù)進(jìn)行最大的程度的解耦,插件化可以使各個部門獨立開發(fā)個字業(yè)務(wù)的app,同時在需要的情況將各自的應(yīng)用集成進(jìn)一個整體的應(yīng)用中,使其可以獨立開發(fā)和發(fā)布,但又可以相互依賴和合并。
2、應(yīng)用無需發(fā)布更新,可以通過下載插件或者補丁的方式在后臺完成修復(fù)或者更新。
動態(tài)代理在插件化技術(shù)中的使用
動態(tài)代理是java設(shè)計模式中代理模式的另一種實現(xiàn),通過JVM在運行期通過反射為委托的接口類動態(tài)的生成代理的一種技術(shù)。目前最火熱的Android網(wǎng)絡(luò)請求的開源庫Retrofit就是基于這種技術(shù)實現(xiàn)的一款Restful Api風(fēng)格的Android網(wǎng)絡(luò)客戶端框架(本篇主要講的是具體的實例技術(shù)在插件化中的應(yīng)用,所以此處不詳細(xì)提,但是推薦大家去看下Retrofit源碼,通過動態(tài)代理去做接口配置的代理,這種設(shè)計思想很棒)。
在目前市面上流行的插件化框架中,動態(tài)代理同樣被廣泛使用。現(xiàn)在我們來看一下最近滴滴才開源的插件化框-VirtualApk中如何使用動態(tài)代理對系統(tǒng)的服務(wù)進(jìn)行hook接管的。

如上圖在demo的MainActivity中,加載插件第一步是初始化了插件的管理器PluginManager這個類。該類為插件化管理的核心類,將加載的插件放在了一個ConcurrentHashMap中進(jìn)行管理。PluginManager.getInstance(base)中實例化了PluginManager并在初始化的時候調(diào)用了prepare()方法。接著看一下這個prepare()方法中的操作。


上圖可以看出,hookSystemServices()方法先通過反射獲取到系統(tǒng)ActivityManagerNative中的IActivityManager接口,然后通過動態(tài)代理的方式,對IActivityManager接口進(jìn)行代理,再用其替換掉系統(tǒng)的達(dá)到接管系統(tǒng)服務(wù)的目的。我們再看該動態(tài)代理的實現(xiàn)。



如上圖所示(部分代碼截圖),該動態(tài)代理類對需要接管的服務(wù),如:startService等進(jìn)行了修改和接管,繞開了系統(tǒng)的限制,判斷了是否是本地啟動和遠(yuǎn)程啟動進(jìn)行了不同的處理。
關(guān)于動態(tài)代理的概念,推薦大家參考這篇文章:www.ibm.com/developerworks/cn/java/j-lo-proxy1/index.html
此處startService方法中根據(jù)入?yún)bject[] args數(shù)組(代理對應(yīng)方法的入?yún)?shù)數(shù)組,此處是IActivityManager接口中方法startService(IApplicationThread caller, Intent service,String resolvedType, String callingPackage,int userId)的入?yún)ⅲ┤^(qū)分來源為本地或插件服務(wù)來進(jìn)行不同的分發(fā)操作。
總結(jié)
代理模式在JAVA中廣泛的應(yīng)用,是AOP編程的一種實現(xiàn)手段。本文只是列舉了動態(tài)代理技術(shù)在插件化框架中的某個功能的實現(xiàn)。其實不管是動態(tài)代理還是靜態(tài)代理,在插件化框架中都有大量的使用去繞過系統(tǒng)的限制達(dá)到加載插件去執(zhí)行宿主中的功能。大家可以先從Android Activity等服務(wù)的啟動流程的源碼閱讀去更深入的了解系統(tǒng)服務(wù)的運行過程,從而找到合適的切入點去代理系統(tǒng)的服務(wù)達(dá)到自己的定制化需求。此外,JVM的動態(tài)代理技術(shù)只能代理接口,原因是在代理類最后都繼承了Proxy這個類,根據(jù)Java的單一繼承規(guī)則,所以只能為接口動態(tài)代理。如果想對抽象類或者類做動態(tài)代理可以采取cglib來實現(xiàn),具體的就不在本文中討論了,大家可以查找相關(guān)的實現(xiàn)或自己去嘗試。關(guān)于插件化中使用到的其他技術(shù),我會一邊學(xué)習(xí)一邊分享給大家,后續(xù)會整理出對應(yīng)的demo。
引用
VirtualApk:github.com/didi/VirtualAPK
動態(tài)代理的概念:www.ibm.com/developerworks/cn/java/j-lo-proxy1/index.html