动态代理概述:
Java提供的动态代理类Proxy:
Proxy provides static methods for creating dynamic proxy classes and instances, and it is also the superclass of all dynamic proxy classes created by those methods.
代理类Proxy提供静态方法用于创建动态代理子类和对象。它也是所有通过这些静态方法所创建的动态代理子类的父类。
其中一个最常用的静态方法就是:
public static Object newProxyInstance(
ClassLoader loader, Class<?>[] interfaces, InvocationHandler handler)
Returns an instance of a proxy class for the specified interfaces that dispatches method invocations to the specified invocation handler.
返回一个实现了所有指定接口的代理子类对象,该对象将方法调用分派给指定的调用处理器。
ClassLoader :被代理类的类加载器,方法内部会调用这个类加载器来获取继承Proxy类的子类字节码文件对象Class,加载的同时该子类也实现所有指定的接口。
Class<?>[] interfaces: 被代理类 的所有实现接口的Class对象,在方法内部会克隆一份加载进Proxy字节码对象中。
表示实现Proxy类实现所有指定接口。
InvocationHandler接口:(调用处理器)
InvocationHandler is the interface implemented by the invocation handler of a proxy instance.
调用处理器是一个通过 代理对象的调用处理器(Handler实现类中的invoke) 来实现的接口
Each proxy instance has an associated invocation handler. When a method is invoked on a proxy instance, the method invocation is encoded and dispatched to the invoke method of its invocation handler.
每一个代理对象都有相关联的调用处理器。 当一个方法伴随所属代理对象被调用,这个方法调用就会被编码转移为调用处理器中的相应扩展方法调用。
总的来讲,每一个proxy代理对象都有一个实现InvocationHandler接口的实现类Handler,这个实现类中的invoke方法就是proxy代理对象的实际调用处理器,在这个invoke方法体中,有所有 被代理对象 的方法逻辑实现和扩展。
每当代理对象proxy被反射机制用于调用其方法时,这个方法调用就自动转移为Handler类里invoke方法体中的对应扩展方法调用。
InvocationHandler这个接口的唯一一个方法 invoke 方法:
Object invoke(Object proxy, Method method, Object[] args) throws Throwable
proxy:代理对象,只是反射机制调用方法的需要
method: proxy被反射机制用于调用的方法对象
args:调用方法的参数列表
动态代理实现:
这里面首先想要做到动态代理,必须先实现这个InvocationHandler接口,然后我们主要看getProxy方法,参数是需要被代理的对象Singer
方法里面有一个Proxy类,这个Proxy类提供了很多方法,这里我们用的是newProxyInstance方法,它有三个参数,第一个是被代理类的类构造器,第二个指的是被代理类的接口,也就是Singer的接口,第三个是实现这个代理过程的类,就是本类。具体的来说,这个方法执行了下面三步:
1.用ClassLoader加载器生成一个实现了参数interfaces里所有接口且继承了Proxy的代理类的字节码对象。
2.使用Proxy的构造函数 Proxy(InvocationHandler h)来创造一个代理类的实例,将我们自定义的InvocationHandler子类传入。
3.返回这个代理类实例对象,因为我们构造的代理类实现了interfaces(也就是我们程序中传入的Singer.class.getInterfaces())里的所有接口,因此返回的代理类可以强转成Star类型来调用接口中定义的方法。
而在调用每个代理类每个方法的时候,都用反射去调InvocationHandler实现类的invoke方法(也就是我们自定义的AutoProxy重写的invoke方法),用参数传递了代理类实例、接口方法、调用参数列表,这样我们在重写的invoke方法中就可以实现对所有方法的统一包装了。