定义:为其他对象提供一种代理以控制对这个对象的访问。代理模式本质上也叫做委托模式,它是一种基本设计技巧,许多其他模式,比如状态模式,策略模式,访问者模式本质上是在特殊场合采用了委托模式。代理模式应用非常广泛,下面举出一个通用示例,假设现有三个角色,抽象主题、具体实现主题、代理主题:
//抽象主题类public interface Subject{ public void request();}//真实主题类public class RealSubject implements Subject{ //实现方法 public void request(){ }}//代理类public class Proxy implements Subject{ //要代理实现哪个类 private Subject subject = null; //默认代理者 public Proxy(){ this.subject = new Proxy(); } //通过构造函数传递代理类 public Proxy(Object... objects){ } //实现接口中定义的方法 public void request(){ this.before(); this.subject.request(); this.after(); } //预处理 private void before(){ } //后处理 private void after(){ }}
代理模式有如下优点:
- 职责清晰。真实的角色就是实现实际的业务逻辑,不用关心其他非本职的事务。
- 高扩展性。具体主题角色是随时都会发生变化的,但只要他实现了接口,不管如何变化,都不会影响到代理类的使用
- 智能化。比如动态代理
代理模式扩展:
上述通用代码是普通代理,还可以改造为强制代理模式,也就是不允许直接new具体对象,必须通过代理产生;还有一种是个性化代理,一个类可以实现多个接口,完成不同任务的整合,代理的目的是在目标对象方法的基础上进行增强,这种增强本质上通常是拦截和过滤目标方法,只需要在普通代理类上实现更多接口即可实现;最后但很重要的一种就是动态代理,什么是动态代理?就是在实现阶段不用关心代理谁,只在运行阶段才指定代理哪个对象。相对而言,自己写代理类就是静态代理。现在非常常见的面向横切面编程,也就是AOP,其核心就是动态代理机制。
提到动态代理,必须说下jdk提供的一个动态代理接口:InvocationHandler,通过这个接口,所有的方法都由该handler来处理,由它接管所有实际的处理任务。下面看一个动态代理通用编程模型,
先看Subject接口,抽象主题类:
public interface Subject{ //业务操作 public void doSomething(String str);}
实现主题类:
//真实主题类public class RealSubject implements Subject{ //业务操作 public void doSomething(String str){ }}
重点的动态代理类:
//动态代理的Handler类 public class MyInvocationHandler implements InvocationHandler{ //被代理的对象 private Object target = null; //传递一个对象 public MyInvocationHandler(Object _obj){ this.target = _obj; } //代理方法 public Object invoke(Object proxy, Method method, Object[] args) throws Throwble{ return method.invoke(this.target, args); }}
所有通过动态代理实现的全部通过invoke()方法调用。动态代理:
public class DynamicProxy{ public static T newProxyInstance(ClassLoader loader,Class interfaces, InvocationHandler h){ //寻找JoinPoint连接点,AOP框架使用元数据定义 if(true){ //执行一个前置通知 (new BeforeAdvice()).exec(); } return (T)Proxy.newProxyInstance(loader, interfaces, h);}public interface IAdvice{ public void exec();}public class BeforeAdvice implements IAdvice{ public void exec(){ }}//场景调用public class Client{ public static void main(String[] args){ Subject subject = new RealSubject(); //定义一个handler InvocationHandler hander = new MyInvocationHandle(subject); //定义主题的代理 Subject proxy = DynamicProxy.newProxyInstance(subject.getClass().getClassLoader(),subject.getClass(),handler); proxy.doSomething("ok");}
在DynamicProxy类中,有这样的方法,
Subject proxy = DynamicProxy.newProxyInstance(subject.getClass().getClassLoader(),subject.getClass(),handler); 该方法重新生成了一个对象,因为要使用代理!注意getInterfaces()这句话,查找所有该类的接口,然后实现接口中所有方法,当然,都是空方法,由谁来具体实现呢? 就是MyInvocationHandle这个对象。于是我们知道了,由InvocationHandler实现接口中所有方法,由其invoke具体接管所有方法的实现。