跟王老师学反射(十一):动态代理
主讲教师:王少华 QQ群号:483773664
学习内容
学会使用动态代理
一、动态代理
动态代理(Dynamic Proxy):相比上一节所实现的静态代理,动态代理具有更强的灵活性,因为它不用在我们设计实现的时候就指定某一个代理类来代理哪一个被代理对象,我们可以把这种指定延迟到程序运行时由JVM来实现。
动态代理(Dynamic proxies)是 Java 1.3 引入的特性,在Java的java.lang.reflect包下提供了一个Proxy类和一个InvocationHandler接口,通过这个类和接口可以生成JDK动态代理对象
二、Proxy和InvocationHandler
(一)Proxy
1 简介
Proxy提供用于创建动态代理和代理对象的静态方法,它也是所有动态代理的父类。如果我们在程序中为一个或多个接口动态生成实现类,就可以使用Proxy来创建动态代理类;如果需要为一个或多个接口动态地创建实现,也可以使用Proxy来创建动态代理实现。
2 Proxy提供以下二个方法用于创建动态代理类和动态代理实例
public static Class<?> getProxyClass(ClassLoader loader,
Class<?>... interfaces):创建一个动态代理类所对应的Class对象,该代理类将实现interfaces所指定的多个接口。第一个ClassLoader指定生成动态代理类的类加载器。
public static Object newProxyInstance(ClassLoader loader,
Class<?>[] interfaces,
InvocationHandler h):直接创建一个动态代理对象,该代理对象的实现类实现了interfaces指定的系列接口,执行代理对象的每个方法时都会被替换执行invocationHandler对象的invoke方法
(二)InvocationHandler
InvocationHandler接口是代理处理程序类的实现接口,该接口作为代理实例的调用处理者的公共父类,每一个代理类的实例都可以提供一个相关的具体调用处理者(InvocationHandler接口的子类)
InvocationHandler接口中有一个方法
1 |
|
参数:
proxy - 被代理的对象
method - 要调用的方法
args - 方法调用时所需要的参数,如果接口方法不使用参数,则为 null。基本类型的参数被包装在适当基本包装器类(如 java.lang.Integer 或 java.lang.Boolean)的实例中。
返回:
从代理实例的方法调用返回的值。如果接口方法的声明返回类型是基本类型,则此方法返回的值一定是相应基本包装对象类的实例;否则,它一定是可分配到声明返回类型的类型。如果此方法返回的值为 null 并且接口方法的返回类型是基本类型,则代理实例上的方法调用将抛出 NullPointerException。否则,如果此方法返回的值与上述接口方法的声明返回类型不兼容,则代理实例上的方法调用将抛出 ClassCastException。
三、动态代理的实现
(一)动态代理的实现步骤
1. 实现InvocationHandler接口创建自己的调用处理器
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
|
2. 给Proxy类提供ClassLoader和代理接口类型数组创建动态代理类
1 2 3 4 5 6 7 |
|
3、通过代理对象调用目标对象方法
1 2 |
|
(二)代码优化
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 |
|
1 2 3 4 5 6 7 |
|