首页 > 代码库 > 代理模式

代理模式

代理模式是一种应用非常广泛的设计模式,当客户端代码需要调用某个对象时,客户端实际上不关心是否准确得到该对象,它只要一个能提供该功能的对象即可,此时我们就可返回该对象的代理(Proxy)。

代理就是一个Java对象代表另一个Java对象来采取行动。如:

public class ImageProxy implements Image {


  //组合一个image实例,作为被代理的对象
  private Image image;
  //使用抽象实体来初始化代理对象
  public ImageProxy(Image image) {
    this.image = image;
  }
  /** * 重写Image接口的show()方法
  * 该方法用于控制对被代理对象的访问,
  * 并根据需要负责创建和删除被代理对象
  */
  public void show()
  {
    //只有当真正需要调用image的show方法时才创建被代理对象
    if(image==null)
    {
      image=newBigImage();

    }

    image.show();

  }

}

调用时,先不创建:

Imageimage=newImageProxy(null);

Hibernate默认启用延迟加载,当系统加载A实体时,A实体关联的B实体并未被加载出来,A实体所关联的B实体全部是代理对象——只有
等到A实体真正需要访问B实体时,系统才会去数据库里抓取B实体所对应的记录。
借助于Java提供的Proxy和InvocationHandler,可以实现在运行时生成动态代理的功能,而动态代理对象就可以作为目标对象使用,而
且增强了目标对象的功能。如:

Panther
publicinterfacePanther{
  //info方法声明

  publicvoidinfo();
  //run方法声明

  publicvoidrun();
}

publicclassGunPantherimplementsPanther{
  //info方法实现,仅仅打印一个字符串
  publicvoidinfo()
  {

    System.out.println("我是一只猎豹!");
  }

  //run方法实现,仅仅打印一个字符串
  publicvoidrun()
  {

    System.out.println("我奔跑迅速");
  }

}

创建代理对象

public class MyProxyFactory{
  

  //为指定target生成动态代理对象

  publicstaticObjectgetProxy(Objecttarget)throwsException

  {

    //创建一个MyInvokationHandler对象
    MyInvokationHandlerhandler=new MyInvokationHandler();

    //为MyInvokationHandler设置target对象
    handler.setTarget(target);  

    //创建、并返回一个动态代理

    returnProxy.newProxyInstance(target.getClass().getClassLoader(),target.getClass().getInterfaces(),handler);

  }

}


增强代理的功能

public class MyInvokationHandler implements InvocationHandler {
  //需要被代理的对象
  private Object target;
  public void setTarget(Object target)
  {
    this.target = target;
  }

  //执行动态代理对象的所有方法时,都会被替换成执行如下的invoke方法
  public Object invoke(Object proxy, Method method, Object[] args) throws Exception
  {
    TxUtil tx = new TxUtil();
    //执行TxUtil对象中的beginTx。
    tx.beginTx();
    //以target作为主调来执行method方法

    Object result = method.invoke(target , args);
    //执行TxUtil对象中的endTx。
    tx.endTx();
    return result;
  }

}

TxUtil
public class TxUtil {

  //第一个拦截器方法:模拟事务开始
  public void beginTx()
  {
    System.out.println("=====模拟开始事务=====");
  }
  //第二个拦截器方法:模拟事务结束
  public void endTx()
  {

    System.out.println("=====模拟结束事务=====");
  }

}


测试
public static void main(String[] args) throws Exception
{

  //创建一个原始的GunDog对象,作为target
  Panther target = new GunPanther();
  //以指定的target来创建动态代理

  Panther panther = (Panther)MyProxyFactory.getProxy(target);
  //调用代理对象的info()和run()方法
  panther.info();
  panther.run();
}


Spring所创建的AOP代理就是这种动态代理。但是Spring AOP更灵活。