目录
前言
记录一下Java中的动态代理相关知识,主要是为了Android中Hook技术要用,因此记录一下,方便自己查阅。
正文
什么是动态代理
利用Java的反射技术,在运行时创建一个实现某些给定接口的新类(动态代理类)。
代理的是接口(Interfaces),不是类(Class),也不是抽象类。
newProxyInstance()
这个方法在java.lang.reflect.Proxy类中。
public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces,InvocationHandler h)throws IllegalArgumentException{ //略 }
三个参数:
ClassLoader:用哪个类加载器去加载代理对象。(可以用当前类的,可以通过当前线程的,后面有介绍)
Class[]:动态代理类需要实现的接口。(重点是接口哈,可以通过实现类获取,也可以直接通过接口获取,后面有介绍)
InvocationHandler:获取接口中的方法,并且动态代理方法执行时,调用invoke方法。
InvocationHandler接口
这个是newProxyInstance()中第三个参数。
public interface InvocationHandler { public Object invoke(Object proxy, Method method, Object[] args)throws Throwable; }
当代理对象执行被代理对象实现的接口中的任意方法都会经过这个invoke方法。
我们可以在这里进行拦截处理。
proxy:代理对象的引用,在方法中如果想使用代理对象,就可以使用它,一般不用
method:被代理对象的方法
args:代理对象的方法所需要的参数
返回值:被代理对象中方法的返回值
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的实现者获取,只是获取的方式存在不一。
参考文章
《》
《》
《》
© 版权声明