文章目录
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 { /** * 目标对象的业务逻辑 */ @Override public 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 来执行 */ @Override public 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"); } }