Java设计模式---代理模式

Posted lzy_tinyjoy

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java设计模式---代理模式相关的知识,希望对你有一定的参考价值。

简述:

    代理模式(Proxy Pattern)是GoF 23种Java常用设计模式之一。代理模式的定义:Provide a surrogate or placeholder for another object to controlaccess to it(为其他对象提供一种代理以控制对这个对象的访问)。使用代理模式创建代理对象,让代理对象控制目标对象的访问(目标对象可以是远程的对象、创建开销大的对象或需要安全控制的对象),并且可以在不改变目标对象的情况下添加一些额外的功能。

代理模式一般涉及到的角色:

    ① 抽象角色:声明真实对象和代理对象的共同接口(该接口一般包含用于处理业务的方法);     ② 代理角色:代理对象角色内部含有对真实对象的引用,从而可以操作真实对象,同时代理对象提供与真实对象相同的接口以便在任何时刻都能代替真实对象。同时,代理对象可以在执行真实对象操作时,附加其他的操作,相当于对真实对象进行封装。     ③ 真实角色:代理角色所代表的真实对象,是我们最终要引用的对象。

UML如下:



代理模式一般分为以下几种形式:     ① 静态代理     ② 动态代理     ③ 正向代理     ④ 反向代理     ⑤ 虚拟代理     ⑥ 缓存代理     ⑦ 保护代理

静态代理:

   上面对代理模式的描述已经完毕,接下里我们只使用代码来实现。 1、首先定义抽象角色接口:即处理业务的公共方法
/**
 * 类描述:抽象主题
 *
 * @author lzy
 *
 */
public interface Subject 
     public void operate();

2、接下来定义用于处理业务的真实角色
/**
 * 类描述:真实代理类
 *
 * @author lzy
 *
 */
public class RealSubject implements Subject 

     @Override
     public void operate() 
          System.out.println("真实代理类正在处理业务逻辑......");
     


    3、代理类
/**
 * 类描述:代理类
 * @author lzy
 *
 */
public class Proxy implements Subject 
     private Subject subject;

     public Proxy(Subject subject) 
          this.subject = subject;
     

     @Override
     public void operate() 
        System.out.println("处理业务前的的操作......");
        subject.operate();
        System.out.println("处理业务完成后的操作......");
     


OK,至此代理模式的角色已经定义完毕,接下来我们写一个测试用的客户端调用一下:
public class Client 
     public static void main(String[] args) 

          Subject subject = new RealSubject();
          Proxy proxy = new Proxy(subject);
          proxy.operate();
     

   我们直接看一下控制台输出的日志信息:
处理业务前的的操作......
真实代理类正在处理业务逻辑......
处理业务完成后的操作......

动态代理:

    动态代理中,代理类并不是在Java代码中实现,而是在运行时期生成,相比静态代理,动态代理可以很方便的对委托类的方法进行统一处理,如添加方法调用次数、添加日志功能等等,动态代理分为jdk动态代理和cglib动态代理。我们先来看一下
    ① 我们首先定义公共接口:
/**
 * 类描述:业务逻辑
 */
public interface DynamicService 
     public void add();

② 定义真实代理角色
/**
 * 类描述:业务逻辑的实现,真实代理角色
 *
 * @author lzy
 *
 */
public class DynamicServiceImpl implements DynamicService 

     @Override
     public void add() 
          System.out.println("This is a add Service");
     

  ③ 利用java.lang.reflect.Proxy类和java.lang.reflect.InvocationHandler接口定义代理类的实现。
/**
 * 类描述:代理类
 *
 * @author lzy
 *
 */
public class MyInvocatioHandler implements InvocationHandler 
     private Object target;

     public MyInvocatioHandler(Object target) 
          this.target = target;
     

     /**
      * @param proxy
      *            代理类对象
      *
      * @param method
      *            被代理的接口方法
      *
      * @param args
      *            被代理接口方法的参数
      */
     @Override
     public Object invoke(Object proxy, Method method, Object[] args) throws Throwable 
          System.out.println("-----before-----");
          Object result = method.invoke(target, args);
          System.out.println("-----end-----");
          return result;
     

     public Object getProxy() 
          ClassLoader loader = Thread.currentThread().getContextClassLoader();
          Class<?>[] interfaces = target.getClass().getInterfaces();
          for (Class<?> class1 : interfaces) 
              System.out.println("接口名:" + class1.getSimpleName());
          
          return Proxy.newProxyInstance(loader, interfaces, this);
     

    来我们看一下日志信息:
-----before-----
This is a add Service
-----end-----

    OK,到此动态代理也就完成了。动态代理的运用非常的广泛,其中一种典型的用法就是拦截器,接下来我们修改一下上面的代理类定义一个简单的拦截器:     首先先定义一个拦截器入下:
/**
 * 类描述:拦截器
 *
 * @author lzy
 *
 */
public class MyInterceptor 
     public void beforeIntercept() 
          System.out.println("处理业务前拦截信息");
     

     public void afterIntercept() 
          System.out.println("处理业务后拦截信息");
     

    修改后的代理类入下:
/**
 * 类描述:代理类
 *
 * @author lzy
 *
 */
public class MyInvocatioHandler implements InvocationHandler 
     private Object target;
     private MyInterceptor interceptor;

     public MyInvocatioHandler(Object target) 
          this.target = target;
          this.interceptor = new MyInterceptor();
     

     /**
      * @param proxy
      *            代理类对象
      *
      * @param method
      *            被代理的接口方法
      *
      * @param args
      *            被代理接口方法的参数
      */
     @Override
     public Object invoke(Object proxy, Method method, Object[] args) throws Throwable 
          interceptor.beforeIntercept();
          Object result = method.invoke(target, args);
          interceptor.afterIntercept();
          return result;
     

     public Object getProxy() 
          ClassLoader loader = Thread.currentThread().getContextClassLoader();
          Class<?>[] interfaces = target.getClass().getInterfaces();
          for (Class<?> class1 : interfaces) 
              System.out.println("接口名:" + class1.getSimpleName());
          
          return Proxy.newProxyInstance(loader, interfaces, this);
     

    日志信息入下:
处理业务前拦截信息
This is a add Service
处理业务后拦截信息

    实现完动态代理以后也就理解了java中的动态代理来实现AOP的拦截功能。说白了,就是在目标类的基础上增加切面逻辑,生成增强的目标类(该切面逻辑或者在目标类函数执行之前,或者目标类函数执行之后,或者在目标类函数抛出异常时候执行。不同的切入时机对应不同的Interceptor的种类,如BeforeInterceptor,AfterInterceptor以及ThrowsInterceptor等)。

以上是关于Java设计模式---代理模式的主要内容,如果未能解决你的问题,请参考以下文章

设计模式学习笔记---结构型---代理模式

代理模式

jdk动态代理底层实现

java动态代理

Java动态代理与Cglib库

java中静态代理和动态代理