【Android 插件化】Hook 插件化框架 ( Hook 技术 | 代理模式 | 静态代理 | 动态代理 )
Android 插件化系列文章目錄
【Android 插件化】插件化簡介 ( 組件化與插件化 )
【Android 插件化】插件化原理 ( JVM 內存數據 | 類加載流程 )
【Android 插件化】插件化原理 ( 類加載器 )
【Android 插件化】“ 插樁式 “ 插件化框架 ( 原理與實現思路 )
【Android 插件化】“ 插樁式 “ 插件化框架 ( 類加載器創建 | 資源加載 )
【Android 插件化】“ 插樁式 “ 插件化框架 ( 注入上下文的使用 )
【Android 插件化】“ 插樁式 “ 插件化框架 ( 獲取插件入口 Activity 組件 | 加載插件 Resources 資源 )
【Android 插件化】“ 插樁式 “ 插件化框架 ( 運行應用 | 代碼整理 )
【Android 插件化】Hook 插件化框架 ( Hook 技術 | 代理模式 | 靜態代理 | 動態代理 )
文章目錄
- Android 插件化系列文章目錄
- 前言
- 一、Hook 技術簡介
- 二、代理機制
- 1、靜態代理示例
- 2、動態代理示例
- 三、博客資源
前言
在之前的系列博客中 , 介紹了 " 插樁式 " 插件化框架 , 該框架存在一些問題 :
開發需要定制 : " 插件 " 模塊中的 Activity 必須集成 BaseActivity , 其中很多操作都需要針對該方式進行 定制化開發 , 與開發普通的應用完全不同 ;
沒有真正的上下文環境 : " 插件 " 模塊內部 , 調用 Activity 組件的 getApplicationContext 方法會出現問題 , 因為 插件內部沒有真正的供應用運行的上下文環境 ;
( 之前的 " 插樁式 " 插件化框架 , 只是簡單示例 , 遠遠達不到能在項目中使用的復雜程度 )
插件化框架 的最終目的是讓 " 插件 " 模塊的開發和使用 , 與正常的應用開發和使用達到完全一致的效果 , " 宿主 " 模塊 與 " 插件 " 模塊 之間可以 無障礙通信 ;
一、Hook 技術簡介
Hook 技術 又稱為 鉤子技術 , 同樣 Hook 函數 也稱為 鉤子函數 ; 鉤子技術 在 系統入侵 中 , 廣泛使用 ;
Hook 技術 沒有硬性規定技術標準 , 只是一種 技術概念 ; 在某一段代碼的運行流程中 , 掛入自定義的鉤子 , 在鉤子的 前面 , 后面 , 可以 插入任意自定義的操作代碼 , 達到 業務注入 的目的 ;
Hook 技術可以理解為 面向切面編程思想 , 想辦法在不修改源碼的前提下 , 在某個方法調用之前 , 插入自己的代碼 , 業務邏輯 ,
Android 中的 Hook 技術 : 通過分析 Android 系統源碼執行 , 通過 動態注入技術 , 在代碼運行的某個階段 , 注入開發者自定義的代碼 ;
常用的動態注入技術 :
① 編譯時修改字節碼數據 : 代碼編譯時修改 Class 字節碼數據 , 如 Dagger ;
② 運行時修改字節碼數據 : 運行時可以修改字節碼文件數據 , 達到代碼入侵的效果 ;
Android 中的 Hook 機制 , 主要涉及到下面兩種技術 :
① 反射機制 : Java 反射機制 ;
② 代理機制 : 動態代理 , 靜態代理 ;
二、代理機制
代理機制 :
存在一個 目標對象 Subject 和 代理者 Proxy ;
目標對象 Subject 執行一些業務邏輯 , 代理者 Proxy 持有 目標對象 Subject , 當 目標對象 Subject 要執行某個方法時 , 通過 代理者 Proxy 調用 目標對象 Subject 中的方法執行 ;
代理者 Proxy 調用 目標對象 Subject 方法 之前 , 之后 , 可以插入自己的業務邏輯 ;
下面簡要介紹 靜態代理 與 動態代理 ;
1、靜態代理示例
定義代理方法接口 : 代理者 和 目標對象 都要實現該接口 , 代理者 和 目標對象 可以進行相互替換 ;
/*** 代理者 和 目標對象 都要實現該接口* 代理者 可以替換 目標對象*/ public interface AInterface {void request(); }目標對象 : 被代理的目標對象 , 實現了
/*** 被代理的目標對象* 目標對象 Subject 執行一些業務邏輯* 代理者 Proxy 持有 目標對象 Subject* 當目標對象 Subject 要執行某個方法時* 通過 代理者 Proxy 調用 目標對象 Subject 中的方法執行*/ public class Subject implements AInterface {/*** 目標對象的業務邏輯*/@Overridepublic void request() {System.out.println("Subject request");} }代理者 :
/*** 代理者* 目標對象 Subject 執行一些業務邏輯* 代理者 Proxy 持有 目標對象 Subject* 當目標對象 Subject 要執行某個方法時* 通過 代理者 Proxy 調用 目標對象 Subject 中的方法執行*/ public class Proxy implements AInterface {/*** 代理者 持有的 目標對象*/private Subject subject;public Proxy(Subject subject) {this.subject = subject;}/*** 當 Subject 需要執行 request 方法時 , 自己不直接執行* 而是通過 Proxy 的該方法調用 持有的 目標對象 Subject 來執行*/@Overridepublic void request() {before();subject.request();after();}/*** 執行 Subject 目標對象的 request 方法前執行的業務邏輯*/private void before() {System.out.println("Proxy before");}/*** 執行 Subject 目標對象的 request 方法后執行的業務邏輯*/private void after() {System.out.println("Proxy after");} }main 函數調用 : 通過代理者調用目標對象中的類 , 并在執行目標對象 Subject 的 request 方法時 , 對該方法進行邏輯增強 ;
① 方式一 :
public class Main {public static void main(String[] args) {// 1. 創建目標對象Subject subject = new Subject();// 2. 創建代理類Proxy proxy = new Proxy(subject);// 3. 通過代理類調用目標對象的方法proxy.request();/*代理類的作用 :執行 目標對象 Subject 的 request 方法時 ,對該方法進行邏輯增強 ;*/} }② 方式二 :
public class Main {public static void main(String[] args) {/*下面的這種用法, 不需要關注目標對象只需要了解 Proxy 代理者調用者不了解目標對象的內部實現細節目標對象也不了解調用者*/AInterface aInterface = new Proxy(new Subject());aInterface.request();} }執行結果 :
Proxy before Subject request Proxy after2、動態代理示例
動態代理接口 :
/*** 代理者 需要實現的接口* 該接口就是動態代理接口*/ public interface AInterface {void request(); }目標對象 : 被代理的目標對象 , 需要實現代理接口 ;
public class Subject implements AInterface {@Overridepublic void request() {System.out.println("Subject request");} }InvocationHandler 實現 : 這是 Hook 鉤子 , 用于向被代理的目標對象的目標方法中注入業務邏輯 ;
import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method;public class AInvocationHandler implements InvocationHandler {/*** 被代理的對象*/Object target;public AInvocationHandler(Object target) {this.target = target;}@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {before();Object object = method.invoke(target, args);after();return object;}/*** 被代理對象方法調用之前執行*/private void before(){System.out.println("AInvocationHandler before");}/*** 被代理對象方法調用之后執行*/private void after(){System.out.println("AInvocationHandler after");} }動態代理執行 main 函數 :
import java.lang.reflect.InvocationHandler; import java.lang.reflect.Proxy;public class Main {public static void main(String[] args) {// 1. 創建目標對象Subject subject = new Subject();// 2. 獲取目標對象類加載器ClassLoader classLoader = subject.getClass().getClassLoader();// 3. 獲取接口 Class 數組, Subject 只實現了一個 AInterface 接口Class<?>[] interfaces = subject.getClass().getInterfaces();// 4. 創建 InvocationHandler , 傳入被代理的目標對象 , 處理該目標對象中被代理的函數InvocationHandler invocationHandler = new AInvocationHandler(subject);// 5. 動態代理 :// ① jdk 根據傳入的參數信息 , 在內存中動態的創建 與 .class 字節碼文件等同的字節碼數據// ② 將字節碼數據 轉為 對應的 字節碼類型// ③ 使用反射調用 newInstance 創建動態代理實例AInterface proxy = (AInterface) Proxy.newProxyInstance(classLoader,interfaces,invocationHandler);// 正式調用被動態代理的類proxy.request();} }執行結果 :
AInvocationHandler before Subject request AInvocationHandler after三、博客資源
博客資源 :
- GitHub :
總結
以上是生活随笔為你收集整理的【Android 插件化】Hook 插件化框架 ( Hook 技术 | 代理模式 | 静态代理 | 动态代理 )的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【FFmpeg】ffplay 播放视频命
- 下一篇: 【错误记录】AS 编译报错 ( Andr