推荐博文:https://blog.csdn.net/pangqiandou/article/details/52964066
利用代理可以在运行时创建一个实现了一组给定接口的新类
这种功能只有在编译时无法确定需要实现那个接口时才有必要使用
1.何时使用代理:
假设有一个表示接口的Class对象(有可能只包含一个接口),它的确切类型在编译时无法知道。这确实有些难度。要想构造一个实现这些接口的类,就需要使用newInstance方法或反射找出这个类的构造器。但是,不能实例化一个接口,需要在程序处于运行状态是定义一个新类
为了解决这个问题,有些程序将会生成代码;将这些代码放置在一个文件中;调用编译器;然后再加载结果类文件。这样做的速度会比较慢,并且需要将编译器与程序放在一起。
代理机制则是一种更好的解决方案,代理类可以在运行时创建全新类。这样的代理类能够实现指定的接口,尤其是,它具有下列方法:
1)指定接口中所需要的全部方法
2)Object类中的全部方法
不能再运行时定义这些方法的新代码,而是提供一个调用处理器
调用处理器是实现了InvocationHandler接口的类对象,这个接口中只有一个方法:object invoke(Object proxy,Method method,Object[] args)
无论何时调用代理对象分方法,调用处理器的invoke方法都会被调用,并向其传递Method对象和原始的调用参数。调用处理器必须给出处理调用的方式
2.创建代理对象:
想要创建一个代理对象,需要使用Proxy类的newProxyInstance方法,这个方法有三个参数:
1)一个类加载器
2)一个Class对象数组
3)一个调用处理器
3.代理类的特性:
代理类是在程序运行过程中创建的。一旦被创建,就变成了常规类
一个代理类只有一个实例域——调用处理器
所有的代理类都覆盖了Object类中的方法toString、equals和hashCode,这些方法仅仅调用了调用处理器的invoke。Object中的其他方法没有被重定义(如clone和getClass)
没有定义代理类的名字,sun虚拟机中的Proxy类将生成一个以字符串$Proxy开头的类名
对于特定的类加载器和预设的一组接口来说,只能有一个代理类,也就是说,如果使用同一个类加载器和接口数组调用两次newProxyInstance方法的话,那么只能得到同一个类的两个对象,也可以利用getProxyClass方法获得这个类:
Class proxyClass = Proxy.getProxyClass(null ,interfaces);
代理类一定是public和final
可以通过调用Proxy类中的isProxyClass方法检测一个特定的Class对象是否代表一个代理类
4.java.lang.reflect.InvocationHandler 1.3:
Object invoke(Object proxy.Method method,Object[] args)
定义了代理对象调用方法是希望执行的动作
5.java.lang.reflect.Proxy:
static Class<?> getProxyClass(ClassLoader loader,Class<?>...interfaces)
返回实现指定接口的代理类
static Object newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler handler)
构造实现指定接口的代理类的一个新实例,所有方法会调用给定处理器对象的invoke方法
static boolean isProxyClass(Class<?> cl)
判断cl是否是一个代理类