Android插件化系列文章目录【Android插件化】插件化介绍(组件化和插件化) ) ) ) ) ) ) ) ) )。
【Android插件化】插件化原理JVM内存数据|类加载过程
【Android插件化】插件化原理(类加载器) )
【Android插件化】“插件式”插件化框架(原理和实现思路) )
【Android插件化】“插件表达式“插件化框架|创建类加载器|资源加载”
【安卓插件】“插件表达式”插件框架(使用注入上下文)
【Android插件】“插件表达式插件框架”(获取插件门户活动组件|加载插件资源)
【Android插件化】“插件表达式”“插件化框架|执行APP |代码整理”
【Android插件】Hook插件框架|hook技术|代理模式|静态代理|动态代理)
文章目录安卓插件系列文章目录前言1、Hook技术简介2、代理机制1、静态代理范例2、动态代理范例3、博客资源
前言在以前的系列博客中,介绍了“打桩式”插件化框架,该框架存在一些问题:
开发需要定制 :'插件'模块的Activity需要与BaseActivity集成,其中许多模块需要根据这种方式定制开发,与常规的APP应用程序开发完全不同;
在33558 www.Sina.com/'插件'模块中调用Activity组件的getApplicationContext方法时,插件中为实际预配而运行的上下文
(以前的“插件表达式”插件框架只是一个简单的示例,远远不及项目中可用的复杂性。)
插件框架的最终目的是使“插件”模块的开发和使用与常规APP应用程序开发和使用完全匹配,从而可以在“主机”模块和“插件”模块之间无障碍地进行通信;
另一方面,Hook技术简介Hook技术也称为钩子技术,同样Hook函数也称为钩子函数; 挂钩技术在系统入侵中被广泛使用;
Hook技术没有硬性规定技术标准,只是技术概念; 在一个代码的执行过程中,可以挂上定制的挂钩,在挂钩的前、后,插入任意定制的操作码,达到业务注入的目的;
Hook技术可以理解为面向切片的编程思想,我们正在寻找在调用某个方法之前插入自己的代码、业务逻辑而不修改源代码的方法
通过分析33558www.Sina.com/Android系统的源代码执行,通过动态注入技术,在代码执行的某个阶段,注入开发者定制的代码;
没有真正的上下文环境 :
Android 中的 Hook 技术 :在代码编译时修改类字节码数据,如Dagger;
常用的动态注入技术 :运行时可以修改字节码文件数据,以达到代码入侵的效果;
安卓的Hook机制主要涉及以下两种技术:
编译时修改字节码数据 :Java反射机制;
运行时修改字节码数据 :动态代理、静态代理;
二、代理机构 反射机制 :
存在目标对象Subject和代理Proxy;
目标对象Subject运行一些业务逻辑,代理Proxy具有目标对象Subject,并且在尝试运行具有目标对象Subject的方法时,将代理Proxy
代理Proxy可以在调用目标对象的Subject方法之前,先插入自己的业务逻辑;
代理机制 :
1、静态代理示例代理机制 :代理和目标对象都必须实现该接口,代理和目标对象可以相互交换;
/**代理和目标对象都必须实现此接口。 *代理是目标对象*/publicinterfaceainterface { 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"); }}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 beforeSubject requestProxy after2、动态代理示例
动态代理接口 :
/** * 代理者 需要实现的接口 * 该接口就是动态代理接口 */public interface AInterface { void request();}目标对象 : 被代理的目标对象 , 需要实现代理接口 ;
public class Subject implements AInterface { @Override public 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; } @Override public 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 beforeSubject requestAInvocationHandler after三、博客资源
博客资源 :
GitHub :