代理模式
代理模式简介
- 原理图
- 简介
代理模式是23个经典模式的一种,又称委托模式。为目标对象提供(包装)了一个代理,这个代理可以控制对目标对象的访问,
外界不用直接访问目标对象,而是访问代理对象,由代理对象再调用目标对象
代理对象中可以添加监控和审查处理
静态代理
代理对象持有目标对象的句柄
所有调用目标对象的方法,都调用代理对象的方法
对每个方法,需要静态编码(理解简单,但需要增加新功能时代码繁琐)
public interface Subject {
public void request();
}
public class SubjectImpl implements Subject {
@Override
public void request() {
System.out.println("i am dealing the request");
}
}
public class StaticProxy implements Subject {
//实际目标对象
private Subject subject;
public StaticProxy(Subject subject) {
this.subject = subject;
}
@Override
public void request() {
System.out.println("preprocess");
subject.request();
System.out.println("postprocess");
}
}
public class StaticProxyDemo {
public static void main(String[] args) {
//创建实际对象
SubjectImpl subjectImpl = new SubjectImpl();
//把实际对象封装到代理对象中
StaticProxy staticProxy = new StaticProxy(subjectImpl);
staticProxy.request();
}
}
动态代理
对目标对象的方法每次调用,进行动态拦截
- 代理处理器
持有目标对象的句柄
实现InvocationHandler接口- 实现invoke方法
- 所有的代理对象方法调用,都会转发到invoke方法来
- invoke的形参method,就是指代理对象方法的调用
- 在invoke内部,可以根据method,使用目标对象不同的方法来响应请求
- 代理对象
根据给定的接口,由Proxy类自动生成的对象
类型com.sun.proxy.$Proxy(),继承自java.lang.reflect.Proxy
通常和目标对象实现同样的接口(可另实现其他的接口)
实现多个接口- 接口的排序非常重要
- 当多个接口里面由方法同名,则默认以第一个接口的方法调用
public interface Subject {
public void request();
}
public class SubjectImpl implements Subject {
@Override
public void request() {
System.out.println("i am dealing the request");
}
}
public class ProxyHandler implements InvocationHandler {
private Subject subject;
public ProxyHandler(Subject subject) {
this.subject = subject;
}
//此方法在代理对象调用任何一个方法时都会被调用
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println(proxy.getClass().getName());
//定义预处理的工作,也可以根据method的不同进行不同的预处理工作
System.out.println("---------before-------");
Object result = method.invoke(subject, args);
System.out.println("--------after---------");
return result;
}
}
public class DynamicProxyDemo {
public static void main(String[] args) {
//创建目标对象
SubjectImpl subjectImpl = new SubjectImpl();
//创建调用处理器对象
ProxyHandler proxyHandler = new ProxyHandler(subjectImpl);
//动态生成代理对象
Subject proxySubject =(Subject) Proxy.newProxyInstance(SubjectImpl.class.getClassLoader(),SubjectImpl.class.getInterfaces(),proxyHandler);
//客户端通过代理对象调用方法,本次调用将自动被代理处理器的invoke方法接收
proxySubject.request();
System.out.println(proxySubject.getClass().getName());
}
}
David Wheeler(函数发明者):All problems in computer science can be solved by another level of indirection