目录
前言
记录一下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的实现者获取,只是获取的方式存在不一。
参考文章
-
《》
-
《》
-
《》
-
历史上的今天
暂无评论...
随机推荐
三毛:故乡人
我们是替朋友的太太去上坟的。朋友坐轮椅,到了墓园的大门口,汽车便不能开进去,我得先将朋友的轮椅从车厢内拖出来,打开,再用力将他移上椅子,然后慢慢的推着他。他的膝上放着一大束血红的玫瑰花,一边讲着闲话,一边往露斯的墓穴走去。那时荷西在奈及利亚工作,我一个人住在岛上。我的朋友尼哥拉斯死了妻子,每隔...
GestureDetector使用简介
前言当用户触摸屏幕的时候,会产生许多手势,例如down,up,scroll,filing等等。为了监听上面各种手势,Android sdk给我们提供了GestureDetector类。GestureDetector 是 Android 中,专门用来进行手势监听的一个对象,在他的监听器中,我们...
海子:麦子熟了
那一年兰州一带的新麦熟了 在回家的路上在水面混了三十多年的父亲还家了坐着羊皮筏子回家来了 有人背着粮食夜里推门进来 灯前认清是三叔老哥俩一宵无言半尺厚的黄土麦子熟了
许知远:窥探者的狂欢节
温斯顿要与一位美丽的姑娘相会,为此,他们必须坐上火车,到一个荒无人烟的野外,这里应该没有监视器,他和那姑娘可以有节制地表露自己的爱意和激情。他们每月如此相会一次,而且地点要经常更换,因为这个世界到处都有“老大哥”的电子眼睛。在乔治·奥威尔充满令人毛骨悚然的想象力的著作《1984》里,监视器是专制统...
Can not perform this action after onSaveInstanceState
java.lang.IllegalStateException异常 Line 151151: 06-14 19:15:46.601 1804 1804 E Media: java.lang.IllegalStateException: Can not perform this action ...
媒体封面流RecyclerCoverFlow左右滚动
前言本文没有创新,使用其他大佬代码进行定制化的,参考文章请看文末。主要是删减了部分功能和增加了无限循环等。记录于此,方便自己翻阅。正文效果如图隐藏内容!付费阅读后才能查看!¥6多个隐藏块只需支付一次付费阅读参考文章《GitHub - ChenLittlePing/Recycler...