动态代理Proxy.newProxyInstance

Java2024年1月12日 am8:08发布7个月前更新 3XCN.COM站长
0 0 0
广告也精彩
目录

前言

记录一下Java中的动态代理相关知识,主要是为了Android中Hook技术要用,因此记录一下,方便自己查阅。

正文

什么是动态代理

利用Java的反射技术,在运行时创建一个实现某些给定接口的新类(动态代理类)。

代理的是接口(Interfaces),不是类(Class),也不是抽象类。

newProxyInstance()

这个方法在java.lang.reflect.Proxy类中。

public static Object newProxyInstance(ClassLoader loader,
    Class<?>[] interfaces,InvocationHandler h)throws IllegalArgumentException{
    //略
}

三个参数:

  1. ClassLoader:用哪个类加载器去加载代理对象。(可以用当前类的,可以通过当前线程的,后面有介绍)

  2. Class[]:动态代理类需要实现的接口。(重点是接口哈,可以通过实现类获取,也可以直接通过接口获取,后面有介绍)

  3. InvocationHandler:获取接口中的方法,并且动态代理方法执行时,调用invoke方法。

InvocationHandler接口

这个是newProxyInstance()中第三个参数。

public interface InvocationHandler {
    public Object invoke(Object proxy, Method method, Object[] args)throws Throwable;
}

当代理对象执行被代理对象实现的接口中的任意方法都会经过这个invoke方法。

我们可以在这里进行拦截处理。

  1. proxy:代理对象的引用,在方法中如果想使用代理对象,就可以使用它,一般不用

  2. method:被代理对象的方法

  3. args:代理对象的方法所需要的参数

  4. 返回值:被代理对象中方法的返回值

Demo

ICar.java
public interface ICar {
    void acc(boolean on);
    void speed(int level);
    void run();
}
AutoCar.java
public class AutoCar implements ICar {
    private final String TAG = getClass().getName();
    @Override
    public void acc(boolean on) {
        Log.d(TAG, "acc on : " + on);
    }
    @Override
    public void speed(int level) {
        Log.d(TAG, "speed level : " + level);
    }
    @Override
    public void run() {
        Log.d(TAG, "run : ");
    }
}
CarHandler.java

实现InvocationHandler接口

public class CarHandler implements InvocationHandler {
    private final String TAG = getClass().getName();
    private final Object mObject;
    //传入需要反射的对象object
    public CarHandler(Object object) {
        mObject = object;
    }
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        //如果要拦截,这里拦截
        Log.d(TAG, "invoke method : "+ method +" , args : "+ Arrays.toString(args));
        return method.invoke(mObject, args);
    }
}
proxy

AutoCar autoCar = new AutoCar();
ICar iCar = (ICar) Proxy.newProxyInstance(
        //当前线程的类加载器
        Thread.currentThread().getContextClassLoader(),
        //动态代理需要实现谁的接口,这里是要代理AutoCar
        autoCar.getClass().getInterfaces(),
        //创建CarHandler,传入要代理的对象,方便反射
        new CarHandler(autoCar)
);
iCar.acc(true);
iCar.run();
iCar.speed(100);
iCar.acc(false);
newProxyInstance()第一个参数

对于newProxyInstance()中第一个参数,除了

Thread.currentThread().getContextClassLoader()

还可以当前类的加载器,比如我是在CarActivity中运行上面代码。

CarActivity.class.getClassLoader()
newProxyInstance()第二个参数

对于newProxyInstance()中第二个参数,除了

autoCar.getClass().getInterfaces()

还可以

AutoCar.class.getInterfaces()

这里传入的是代理的接口,还可以是AutoCar继承的接口ICar

new Class[]{ICar.class}

注意:前面两个通过是ICar实现类或对象获取,最后一个是直接通过ICar创建!!!!

现实中,我们可能通过Interface,也可以通过Interface的实现者获取,只是获取的方式存在不一。

参考文章

  1. java动态代理Proxy.newProxyInstance

  2. 动态代理

  3. java使用动态代理Proxy.newProxyInstance...

  4. 《Android插件化开发指南-包建强》

 历史上的今天

版权声明 1、 本站名称: 91易搜
2、 本站网址: 91es.com3xcn.com
3、 本站文章: 部分来源于网络,仅供站长学习和参考,若侵权请留言
广告也精彩

相关文章

广告也精彩

暂无评论

评论审核已启用。您的评论可能需要一段时间后才能被显示。

暂无评论...

网站升级中

公告

近期网站升级中,可能存在一些bug。欢迎反馈 https://www.91es.com/we.html

本站域名

本站域名 : 91es.com3xcn.com。本站邮箱 : 站长邮箱 i@oorr.cn,通知邮箱we@oorr.cn ,如有更新,请看公告 。