18.5.1使用Proxy和InvocationHandler创建动态代理
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()
方法。