Java的动态代理(代理模式)
-
代理类与委托类有同样的接口,代理类主要负责为委托类预处理消息、过滤消息、把消息转发给委托类,以及事后处理消息等。
-
代理类的对象本身并不真正实现服务,而是通过调用委托类的对象的相关方法,来提供特定的服务。(如调用method.invoke()方法)
-
代理模式最主要的就是有一个公共接口,一个具体的类,一个代理类,代理类持有具体类的实例,代为执行具体类实例方法。
动态代理的实现
- 创建一个与代理对象相关联的InvocationHandler
InvocationHandler foodHandler = new FoodInvocationHandler<Food>(food);
- 使用Proxy类的getProxyClass静态方法生成一个动态代理类
Class<?> foodProxyClass = Proxy.getProxyClass(Food.class.getClassLoader(), new Class<?>[] {Food.class});
- 获得动态代理类中一个带InvocationHandler参数的构造器constructor
Constructor<?> constructor = foodProxyClass.getConstructor(InvocationHandler.class);
- 通过构造器constructor来创建一个动态实例foodProxy
Food foodProxy = (Food) cons.newInstance(foodHandler);
自定义的FoodInvocationHandler类如下:
public class FoodInvocationHandler<T> implements InvocationHandler {
//invocationHandler持有的被代理对象
T target;
public FoodInvocationHandler(T target) {
this.target = target;
}
/**
* proxy:代表动态代理对象
* method:代表正在执行的方法
* args:代表调用目标方法时传入的实参
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//插入方法调用前的操作,如日志输出,计时等
Object result = method.invoke(target, args);
//插入方法调用后的操作
return result;
}
}
使用动态代理的例子:
public class ProxyTest {
public static void main(String[] args) {
//创建一个实例对象,这个对象是被代理的对象
Food food = new Food("葡萄");
//创建一个与代理对象相关联的InvocationHandler
InvocationHandler foodHandler = new FoodInvocationHandler<Food>(food);
//创建一个代理对象foodProxy来代理food,代理对象的每个执行方法都会替换执行Invocation中的invoke方法
Food foodProxy = (Food) Proxy.newProxyInstance(Food.class.getClassLoader(), new Class<?>[]{Food.class}, foodHandler);
//代理被代理类中的方法
foodProxy.xxx();
}
}
动态代理的进一步理解
生成代理类的构造方法,方法参数为InvocationHandler类型,看到这,而构造方法中则调用父类Proxy的构造方法。实际上,代理对象持有一个InvocationHandler对象,InvocationHandler对象持有一个被代理的对象,而在InvocationHandler的invoke方法中,通过调用传入的method参数的invoke方法实现调用被代理对象的方法,而method传入的对象就是InvocationHandler中的成员变量,即被代理类的对象。