Android Hook 技术——动态代理

我们在上一篇 Android Hook 技术——反射技术 对反射技术做了详细讲解,我们这篇对动态代理做详细讲解.

如何正确理解反射和动态代理

    1. 反射 主要是指程序可以访问,检测和修改它本身状态或行为的一种能力,并能根据自身行为的状态和结果,调整或修改应用所描述行为的状态和相关的语义
    1. 动态代理 主要使用反射机制为其他对象提供一种代理以控制对这个对象的访问。某些情况下,一个对象不适合或者不能直接引用另一个对象,而代理对象可以再两者之间起到中介作用。运行阶段才指定代理哪个对象。

组成因素

  • 抽象类接口
  • 被代理类(具体实现抽象类接口的类)
  • 动态代理类,实际调用被代理类的方法和属性

实现步骤

    1. 定义一个委托类和公共接口。
    1. 自己定义一个类(调用处理器类,即实现 InvocationHandler 接口),这个类的目的是指定运行时将生成的代理类需要完成的具体任务,即代理类调用任何方法都会经过这个调用处理器类。
    1. 生成代理对象(当然也会生成代理类),需要为他指定
      (1)委托对象
      (2)实现的一系列接口
      (3)调用处理器类的实例。因此可以看出一个代理对象对应一个委托对象,对应一个调用处理器实例。

动态代理 Proxy / InvocationHandler

  • 在java的动态代理机制中,有两个重要的类和接口,一个是 InvocationHandler(Interface)、另一个则是 Proxy(Class),这一个类和接口是实现我们动态代理所必须用到的。
  • 每一个动态代理类都必须要实现InvocationHandler这个接口(代码中的中介),并且每个代理类的实例都关联到了一个handler,当我们通过代理对象调用一个方法的时候,这个方法的调用就会被转发为由InvocationHandler这个接口的 invoke(对方法的增强就写在这里面) 方法来进行调用。
Java 实现动态代理主要涉及以下几个类:
  • java.lang.reflect.Proxy: 这是生成代理类的主类,通过 Proxy类 生成的代理类都继承了 Proxy 类
  • java.lang.reflect.InvocationHandler: 这里称他为"调用处理器",他是一个接口,我们动态生成的代理类需要完成的具体内容需要自己定义一个类,而这个类必须实现InvocationHandler 接口

实例解析

[1] 我们先定义一个接口:People.java

package com.thtf.leanpackage.plugin_hook.simple_demo;

public interface People {

    public String work();
}

[2] 我们声明一个类对这个接口进行实现:Teacher.java

package com.thtf.leanpackage.plugin_hook.simple_demo;

public class Teacher implements People {
    String name = "aaaaaaa";
    Teacher mTeacher;

    Teacher getTeacher() {
        if (mTeacher == null)
            mTeacher = new Teacher();
        return mTeacher;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public String work() {
        System.out.println(name + "老师教书育人...");
        return "教书的是" + name + "老师";
    }

}

[3] 接下来我们声明一个抽象类,作用是声明两个方法分别实现在执行invoke()之前的操作和之后的操作:MethodInvokeDelegate .java

package com.thtf.leanpackage.plugin_hook.plugin_instance;

import java.lang.reflect.Method;

public abstract class MethodInvokeDelegate {

    public Object beforeInvoke(Object target, Method method, Object[] args) {
        return null;
    }

    public Object afterInvoke(Object target, Method method, Object[] args, Object beforeInvoke, Object invokeResult) {
        if (beforeInvoke != null) {
            return beforeInvoke;
        }
        return invokeResult;
    }

}

[4]接下来我们声明一个类实现MethodInvokeDelegate抽象类并实现InvocationHandler接口WorkHandler.java

package com.thtf.leanpackage.plugin_hook.simple_demo;

import com.thtf.leanpackage.plugin_hook.plugin_instance.MethodInvokeDelegate;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

public class WorkHandler extends MethodInvokeDelegate implements InvocationHandler {

    //代理类中的真实对象
    private Object obj;

    @Override
    public Object beforeInvoke(Object target, Method method, Object[] args) {
        System.out.println("执行了beforeInvoke.......");
        return super.beforeInvoke(target, method, args);
    }

    @Override
    public Object afterInvoke(Object target, Method method, Object[] args, Object beforeInvoke, Object invokeResult) {
        System.out.println("执行了AfterInvoke.......");
        return super.afterInvoke(target, method, args, beforeInvoke, invokeResult);
    }

    //构造函数,给我们的真实对象赋值
    public WorkHandler(Object obj) {
        this.obj = obj;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        Object before = beforeInvoke(obj, method, args);
        //在真实的对象执行之前我们可以添加自己的操作
        System.out.println("before invoke。。。");
        Object invoke = method.invoke(obj, args);
        //在真实的对象执行之后我们可以添加自己的操作
        System.out.println("after invoke。。。");
        return afterInvoke(obj, method, args, before, "哈哈哈");
    }

}


[5] 主程序实现我们的动态代理:Test.java

package com.thtf.leanpackage.plugin_hook.simple_demo;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;

public class Test {
    public static void main(String[] args) {
        //要代理的真实对象
        People people = new Teacher();
        //代理对象的调用处理程序,我们将要代理的真实对象传入代理对象的调用处理的构造函数中,最终代理对象的调用处理程序会调用真实对象的方法
        InvocationHandler handler = new WorkHandler(people);
        /**
         * 通过Proxy类的newProxyInstance方法创建代理对象,我们来看下方法中的参数
         * 第一个参数:people.getClass().getClassLoader(),使用handler对象的classloader对象来加载我们的代理对象
         * 第二个参数:people.getClass().getInterfaces(),这里为代理类提供的接口是真实对象实现的接口,这样代理对象就能像真实对象一样调用接口中的所有方法
         * 第三个参数:handler,我们将代理对象关联到上面的InvocationHandler对象上
         */
        People proxy = (People) Proxy.newProxyInstance(people.getClass().getClassLoader(), people.getClass().getInterfaces(), handler);
        //System.out.println(proxy.toString());
        System.out.println(proxy.work());
    }

}

动态代理限制

从动态代理的使用方法中我们看到,其实可以被增强的方法都是实现了接口的(不实现接口的public方法也可以通过继承被代理类来使用)

参考文章

代理模式及Java实现动态代理
java动态代理机制--那些让你面试脱颖而出的技能
java面试题(杨晓峰)---第六讲谈谈动态代理是基于什么原理?

This ALL! Thanks EveryBody!

你可能感兴趣的:(Android Hook 技术——动态代理)