创建动态代理类会使用到java.lang.reflect.Proxy类和java.lang.reflect.InvocationHandler接口。java.lang.reflect.Proxy主要用于生成动态代理类Class、创建代理类实例,该类实现了java.io.Serializable接口。
java.lang.reflect.Proxy类主要方法如下:
package java.lang.reflect;import java.lang.reflect.InvocationHandler;/*** Creator: yz* Date: 2020/1/15*/public class Proxy implements java.io.Serializable {// 省去成员变量和部分类方法.../*** 获取动态代理处理类对象** @param proxy 返回调用处理程序的代理实例* @return 代理实例的调用处理程序* @throws IllegalArgumentException 如果参数不是一个代理实例*/public static InvocationHandler getInvocationHandler(Object proxy)throws IllegalArgumentException {...}/*** 创建动态代理类实例** @param loader 指定动态代理类的类加载器* @param interfaces 指定动态代理类的类需要实现的接口数组* @param h 动态代理处理类* @return 返回动态代理生成的代理类实例* @throws IllegalArgumentException 不正确的参数异常*/public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)throws IllegalArgumentException {...}/*** 创建动态代理类** @param loader 定义代理类的类加载器* @param interfaces 代理类要实现的接口列表* @return 用指定的类加载器定义的代理类,它可以实现指定的接口*/public static Class<?> getProxyClass(ClassLoader loader, Class<?>... interfaces) {...}/*** 检测某个类是否是动态代理类** @param cl 要测试的类* @return 如该类为代理类,则为 true,否则为 false*/public static boolean isProxyClass(Class<?> cl) {return java.lang.reflect.Proxy.class.isAssignableFrom(cl) && proxyClassCache.containsValue(cl);}/*** 向指定的类加载器中定义一个类对象** @param loader 类加载器* @param name 类名* @param b 类字节码* @param off 截取开始位置* @param len 截取长度* @return JVM创建的类Class对象*/private static native Class defineClass0(ClassLoader loader, String name, byte[] b, int off, int len);}
java.lang.reflect.InvocationHandler接口用于调用Proxy类生成的代理类方法,该类只有一个invoke方法。java.lang.reflect.InvocationHandler接口代码(注释直接搬的JDK6中文版文档):
package java.lang.reflect;import java.lang.reflect.Method;/*** 每个代理实例都具有一个关联的调用处理程序。对代理实例调用方法时,将对方法调用进行编码并* 将其指派到它的调用处理程序的 invoke 方法。*/public interface InvocationHandler {/*** 在代理实例上处理方法调用并返回结果。在与方法关联的代理实例上调用方法时,将在调用处理程序上调用此方法。** @param proxy 在其上调用方法的代理实例* @param method 对应于在代理实例上调用的接口方法的 Method 实例。Method 对象的声明类将是在其中声明* 方法的接口,该接口可以是代理类赖以继承方法的代理接口的超接口。* @param args 包含传入代理实例上方法调用的参数值的对象数组,如果接口方法不使用参数,* 则为 null。基本类型的参数被包装在适当基本包装器类(如 java.lang.Integer* 或 java.lang.Boolean)的实例中。* @return 从代理实例的方法调用返回的值。如果接口方法的声明返回类型是基本类型,* 则此方法返回的值一定是相应基本包装对象类的实例;否则,它一定是可分配到声明返回类型的类型。* 如果此方法返回的值为 null 并且接口方法的返回类型是基本类型,则代理实例上的方法调用将抛出* NullPointerException。否则,如果此方法返回的值与上述接口方法的声明返回类型不兼容,* 则代理实例上的方法调用将抛出 ClassCastException。* @throws Throwable 从代理实例上的方法调用抛出的异常。该异常的类型必须可以分配到在接口方法的* throws 子句中声明的任一异常类型或未经检查的异常类型 java.lang.RuntimeException 或* java.lang.Error。如果此方法抛出经过检查的异常,该异常不可分配到在接口方法的 throws 子句中* 声明的任一异常类型,代理实例的方法调用将抛出包含此方法曾抛出的异常的*/public Object invoke(Object proxy, Method method, Object[] args) throws Throwable;}
