代理模式
一、代理模式原理
代理是一种常用的设计模式,其目的就是为某个对象提供一个代理以控制对该对象的访问。代理类负责为委托类 预处理消息、过滤消息、转发消息,以及进行消息被委托类执行后的后续处理。
图 1. 代理模式
为了保持行为的一致性,***代理类ProxySubject**和**委托类RealSubject*会实现相同的接口,所以在访问者看来两者没有丝毫的区别。通过代理类这中间一层,能有效控制对委托类对象的直接访问,也可以很好地隐藏和保护委托类对象,同时也为实施不同控制策略预留了空间,从而在设计上获得了更大的灵活性。Java 动态代理机制以巧妙的方式近乎完美地实践了代理模式的设计理念。
二、静态代理
1、业务接口
interface Sell{
void sell();
}
2、厂家类
class Factory implements Sell{
@Override
public void sell(){
System.out.println("销售");
}
}
3、代理类
class Proxy{
private Factory factory=new Factory();
public void sell(){
factory.sell();
System.out.println("收取差价");
}
}
4、用户类
class User{
private Proxy proxy;
public void sell(){
proxy.sell();
}
}
使用静态的代理,用户不用直接操作厂家,而是通过代理来实现业务操作,而且代理类可以对业务操作进行增强,但是静态代理,每当有业务增加时,都要新建一个代理类,这样代理类的数量会大幅增多,代码量翻倍,使开发效率变低。
因此,引入了动态代理的方式,自动创建代理实例。不用手写代理类了。
三、动态代理
1、动态代理代码
class ProxyInvocationHandler<E> implements InvocationHandler{
//被代理业务接口
private E e;
public void setSell(E e){
this.e=e;
}
//生成代理类对象
public Object getProxy(){
return Proxy.newProxyInstance(this.getClass().getClassLoader(),e.getClass().getInterfaces,this);
}
//处理代理实例,并返回结果
public Object invoke(Object proxy,Method method,Obejct[] args)throws Throwable{
//增强代码
Object result=method.invoke(e,args);
//增强代码
return result;
}
}
invoke的参数列表:
Object proxy 是 $Proxy0
Obejct[] args 是 被代理的对象(实现业务接口的对象)
2、动态代理基础理论
1、Proxy 类和 InvocationHandler 接口
在java的动态代理机制中,有两个重要的类或接口,一个是 InvocationHandler(Interface)、另一个则是 Proxy(Class),这一个类和接口是实现我们动态代理所必须用到的。首先我们先来看看java的API帮助文档是怎么样对这两个类进行描述的:java.lang.reflect.Proxy:这是 Java 动态代理机制的主类,它提供了一组静态方法来为一组接口动态地生成代理类及其对象。
Proxy 的静态方法:
// 方法 1: 该方法用于获取指定代理对象 所关联的****调用处理器**,参数:代理对象(Object proxy)**
static InvocationHandler getInvocationHandler(Object proxy)
// 方法 2:该方法用于获取动态代理类的*类对象*,参数:1、委托对象的类装载器,2、委托对象的一组接口。
static Class getProxyClass(ClassLoader loader, Class[] interfaces)
// 方法 3:该方法用于判断指定类对象****是否是一个动态代理类,参数:类对象
static boolean isProxyClass(Class cl)
// 方法 4:该方法用于生成动态代理类实例,参数:1、委托对象的类装载器,2、委托对象的一组接口,3、调用处理器
static Object newProxyInstance(ClassLoader loader, Class[] interfaces,InvocationHandler h)
java.lang.reflect.InvocationHandler:
这是调用处理器接口,它自定义了一个 invoke 方法,用于集中处理在动态代理类对象上的方法调用,通常在该方法中实现对委托类的代理访问。
Object invoke(Object proxy, Method method, Object[] args)
这是调用处理器接口,它自定义了一个 invoke 方法,用于集中处理在动态代理类对象上的方法调用,通常在该方法中实现对委托类的代理访问。
Object invoke(Object proxy, Method method, Object[] args)
// 该方法负责集中处理动态代理类上的所有方法调用。参数:1、动态代理类对象,2、被调用的方法对象,3、调用参数。调用处理器根据这三个参数进行预处理或分派到委托类实例上发射执行。