18.5.1使用Proxy和InvocationHandler创建动态代理
在Java的java.lang.reflect包下提供了一个Proxy类和一个InvocationHandler接口,通过使用这个类和接口可以生成JDK动态代理类或动态代理对象Proxy提供了用于创建动态代理类和代理对象的静态方法,它也是所有动态代理类的父类。
- 如果在程序中为一个或多个接口动态地生成实现类,就可以使用
Proxy来创建动态代理类; - 如果需要为一个或多个接口动态地创建实例,也可以使用
Proxy来创建动态代理实例。
创建动态代理类和动态代理实例的方法
Proxy提供了如下两个方法来创建动态代理类和动态代理实例。
| 方法 | 描述 |
|---|---|
static Class<?> getProxyClass(ClassLoader loader, Class<?>... interfaces) |
创建一个动态代理类所对应的 Class对象,该代理类将实现 interfaces所指定的多个接口。第一个 ClassLoader参数指定生成动态代理类的类加载器。 |
static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) |
直接创建一个动态代理对象,该代理对象的实现类实现了 interfaces指定的系列接口,执行代理对象的每个方法时都会被替换执行 Invocation Handler对象的 invoke方法 |
| ## 每个代理对象都有一个与之关联的InvocationHandler对象 ## | |
实际上,即使采用第一个方法生成动态代理类之后,如果程序需要通过该代理类来创建对象,依然需要传入一个InvocationHandler对象。也就是说,系统生成的每个代理对象都有一个与之关联的InvocationHandler对象。 |
程序中可以采用先生成一个动态代理类,然后通过动态代理类来创建代理对象的方式生成一个动态代理对象。代码片段如下:
1 | // 创建一个InvocationHandler对象 |
下面程序示范了使用Proxy和InvocationHandler来生成动态代理对象。
1 | import java.lang.reflect.*; |
上面程序首先提供了一个Person接口,该接口中包含了walk()和sayHello()两个抽象方法,接着定义了一个简单的InvocationHandler实现类,定义该实现类时需要重写invoke()方法——调用代理对象的所有方法时都会被替换成调用该invoke()方法。该invoked方法中的三个参数解释如下:
proxy:代表动态代理对象。method:代表正在执行的方法。args:代表调用目标方法时传入的实参。
上面程序中第一行粗体字代码创建了一个InvocationHandler对象,第二行粗体字代码根据InvocationHandler对象创建了一个动态代理对象。运行上面程序,效果如下:
1 | ----正在执行的方法:public abstract void Person.walk() |
不管程序是执行代理对象的walk()方法,还是执行代理对象的sayhello()方法,实际上都是执行InvocationHandler对象的invoked方法。
本文重点
执行代理对象的方法,实际上是执行InvocationHandler对象的invoke()方法。