Proxy与InvocationHandler
什么叫动态代理类和动态代理对象?其实就是可以这么理解:假设有一个接口,接口是不能被实例化的,就是不能有对象的,它就是规范。而要想使用接口里的方法,必须通过实现implements该接口,重写里面的方法,这个类就是该接口的实现类。这个实现类的new的对象就是实现类对象。
而动态代理类就是这个接口的一个实现类,只不过这个实现类不是我们自己手动implements的,是我们通过JDK的Proxy类让它帮我们生成的这个实现类,这个实现类实现了该接口的所有方法。这个实现类也可以有对象(实例)。所以这个实现类不是我们自己手动实现的,所以专业名词叫动态代理类,这个对象也并不是我们自己new出来的,所以专业名词动态代理对象。
而JDK为我们提供了一个Proxy类,这个类就是专门为我们提供生成动态代理类和对象的方法,通过JDK的API可查看。
Proxy提供了如下两个方法来创建动态代理类和动态代理对象
- static Class<?> getProxyClass(ClassLoader loader,Class<?>...interfaces):创建一个动态代理类所对应的Class对象,一个Class对象是类加载的时候JVM通过ClassLoader为我们生成的,而这里我们需要手动指定来生成,因为我们不是一上来就初始化好的,而是程序运行到这一步了,才要生成一个新类,应该加载一下该类。产生一个新类,是需要类加载器进行初始化的,所以第一个参数是ClassLoader参数指定生成动态代理类的类加载器。第二个是要指明,你想要生成的该实现类实现哪些接口呀,然后通过该Class其实底层就会找到这些接口,就会知道该接口有哪些方法了。这也是反射的原理的呀。
- static Object newProxyInstance(ClassLoader locader,Class<?>[] interfaces,InvocationHandler h):这个方法更便捷,直接为你创建一个动态代理对象。其实也是先有动态代理类,再有动态代理对象的。这就是为什么一个动态代理类对象都有一个与之关联的InvocationHandler对象。
看下图源代码就知道:
1、第一张图是直接getProxyClass
2、第二张图是newProxyInstance时,也调用了getProxyClass0()方法,就是先创建了动态代理类,获取到动态代理类的Class对象,调用该Class对象的Constructor对象,获取到该动态代理类的构造器,将InvocationHandler对象当作参数传递给该动态代理类,创建一个动态代理对象,说明该动态代理对象里面就包含了该InvocationHandler对象。这是JDK规定,所以我们使用Proxy生成动态代理对象时,必须传递一个InvocationHandler对象进去,就说明生成的代理对象就包含了这个InvocationHandler对象,方便接下来的操作。现在我们理解了InvocationHandler是如何被传递进来的了,接下来就可以理解,为啥InvocationHandler里面的方法被调用了。所以我们知道了这一步其实就是将该InvocationHandler类型的对象封装进动态代理类对象里。但是因为InvocationHandler是个接口,所以我们手动给它implements一个实现类。
3、所以在创建这个动态代理实现类实现原接口的各个方法时,里面肯定包含一个通用的方法,就是去InvocationHandler类型的变量的invoke方法,并把该动态代理对象也就是自己,自己的调用方法,自己需要的参数都传给InvocationHandler的invoke方法了。