代理是基本的设计模式之一,它是你为了提供额外的或不同的操作,而插入的用来代替“实际”对象的对象。这些操作通常涉及与“实际”对象的通信,因此代理通常充当着中间人的角色。下面是一个用来展示代理结构的简单示例:

interface Interface {void doSomething();void somethingElse(String arg);
}class RealObject implements Interface {@Overridepublic void doSomething() {System.out.println("doSomething");}@Overridepublic void somethingElse(String arg) {System.out.println("somethingElse " + arg);}
}class SimpleProxy implements Interface {private Interface proxied;public SimpleProxy(Interface proxied) {this.proxied = proxied;}@Overridepublic void doSomething() {System.out.println("SimpleProxy doSomething");proxied.doSomething();}@Overridepublic void somethingElse(String arg) {System.out.println("SimpleProxy somethingElse " + arg);proxied.somethingElse(arg);}
}public class SimpleProxyDemo {public static void consumer(Interface iface) {iface.doSomething();iface.somethingElse("bonobo");}public static void main(String[] args) {consumer(new RealObject());consumer(new SimpleProxy(new RealObject()));}
}

因为consumer()接受的Interface,所以它无法知道正在获得的到底是RealObject还是SimpleProxy,因为这二者都实现了Interface。但是SimpleProxy已经被插入到了客户端和RealObject之间,因此它会执行操作,然后调用RealObject上相同的方法。

在任何时刻,只要你想要将额外的操作从“实际”对象中分离到不同的地方,特别是当你希望能够很容易地做出修改,从没有使用额外操作转为使用这些操作,或者反过来时,代理就显得很有用。(设计模式的关键就是封装修改——因此你需要修改事务以证明这种模式的正确性)。例如,如果你希望跟踪对RealObject中的方法的调用,或者希望度量这些方法调用的开销,那么你应该怎样做呢?这些代码肯定是你不希望将其合并到应用中的代码,因此代理使得你可以很容易地添加或移除它们。

java的动态代理比代理的思想更向前迈进了一步,因为它可以动态地创建代理并动态地处理对所代理方法的调用。在动态代理上所做的所有调用都会被重定向到单一的调用处理器上,它的工作是揭示调用的类型并确定相应的对策。下面是用动态代理重写的SimpleProxyDemo.java:

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;class DynamicProxyHandler implements InvocationHandler {private Object proxied;public DynamicProxyHandler(Object proxied) {this.proxied = proxied;}@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {System.out.println("**** proxy: " + proxy.getClass() + ", method: " + method + ", args: " + args);if (args != null)for (Object arg : args)System.out.println(" " + arg);return method.invoke(proxied, args);}
}public class SimpleDynamicProxy {public static void consumer(Interface iface) {iface.doSomething();iface.somethingElse("bonobo");}public static void main(String[] args) {RealObject real = new RealObject();consumer(real);Interface proxy = (Interface) Proxy.newProxyInstance(Interface.class.getClassLoader(),new Class[] { Interface.class }, new DynamicProxyHandler(real));consumer(proxy);}
}

通过调用静态方法Proxy.newProxyInstance()可以创建动态代理,这个方法需要得到一个类加载器(你通常可以从已经被加载的对象中获取其类加载器,然后创建它),一个你希望该代理实现的接口列表(不是类或抽象类),以及InvocationHandler接口的一个实现。动态代理可以将所有的调用重定向到调用处理器,因此通常会向调用处理器的构造器传递给一个“实际”对象的引用,从而使得调用处理器在执行其中介任务时,可以将请求转发。

invoke()方法中传递进来了代理对象,以防你需要区分请求的来源,但是在许多情况下,你并不关心这一点。然而,在invoke()内部,在代理上调用方法时需要格外当心,因为对接口的调用将被重定向为对代理的调用。

通常,你会执行被代理的操作,然后使用Method.invoke()将请求转发给被代理对象,并传入必须的参数。这初看起来可能有些受限,就像你只能执行泛化操作一样。但是,你可以通过传递其他的参数,来过滤某些方法调用:

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;class MethodSelector implements InvocationHandler {private Object proxied;public MethodSelector(Object proxied) {this.proxied = proxied;}@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {if (method.getName().equals("interesting"))System.out.println("Proxy detected the interesting method");return method.invoke(proxied, args);}
}interface SomeMethods {void boring1();void boring2();void interesting(String arg);void boring3();
}class Implementation implements SomeMethods {@Overridepublic void boring1() {System.out.println("boring1");}@Overridepublic void boring2() {System.out.println("boring2");}@Overridepublic void interesting(String arg) {System.out.println("interesting " + arg);}@Overridepublic void boring3() {System.out.println("boring3");}
}public class SelectingMethods {public static void main(String[] args) {SomeMethods proxy = (SomeMethods) Proxy.newProxyInstance(SomeMethods.class.getClassLoader(),new Class[] { SomeMethods.class }, new MethodSelector(new Implementation()));proxy.boring1();proxy.boring2();proxy.interesting("bonobo");proxy.boring3();}
}

这里,我们只查看了方法名,但是你还可以查看方法签名的其他方面,甚至可以搜索特定的参数值。

如果本文对您有很大的帮助,还请点赞关注一下。

类型信息(7):动态代理相关推荐

  1. 动态代理的原理及其应用

    动态代理的介绍 动态代理是一种在运行时动态地创建代理对象,动态地处理代理方法调用的机制. 实际上它是一种代理机制.代理可以看做是对调用目标的一个封装,直接通过代理来实现对目标代码的调用 与静态代理的比 ...

  2. 动态代理:1 个经纪人如何代理 N 个明星

    在 代理模式:女朋友这么漂亮,你缺经纪人吗? 中我们用宝强的例子介绍了静态代理模式的概念. 本来我的目的是通过大家耳熟能详的例子来加深理解,但是有些网友指责我"没底线"." ...

  3. Java设计模式学习06——静态代理与动态代理(转)

    原地址:http://blog.csdn.net/xu__cg/article/details/52970885 一.代理模式 为某个对象提供一个代理,从而控制这个代理的访问.代理类和委托类具有共同的 ...

  4. 【设计模式】代理模式 ( 动态代理 )

    文章目录 一.动态代理使用流程 二.动态代理代码示例 1.订单类 2.Service 接口 3.Service 实现类 4.Service 静态代理类 5.Dao 接口 6.Dao 实现类 7.Ser ...

  5. JAVA的静态代理与动态代理比较--转载

    扩展:http://www.ibm.com/developerworks/cn/java/j-lo-proxy1/JAVA的静态代理与动态代理比较 一.概念 代理模式是常用的Java 设计模式,它的特 ...

  6. Java动态代理实现(转载\整理)

    在深入解析MapReduce架构设计与实现原理一书中读到动态代理这个东东. 代理是一种常用的设计模式,其目的是为其他对象提供一种代理一控制对这个对象的访问.代理类负责为委托类进行预处理(如安全检查.权 ...

  7. 代理模式 静态代理、JDK动态代理、Cglib动态代理

    1 代理模式 使用代理模式时必须让代理类和被代理类实现相同的接口: 客户端通过代理类对象来调用被代理对象方法时,代理类对象会将所有方法的调用分派到被代理对象上进行反射执行: 在分派的过程中还可以添加前 ...

  8. java动态代理两种实现方式

    代理顾名思义就是代理别人完成某件任务,比如张三代理李四去交物业费.张三就是代理人,李四就是被代理人. Java代理实现,有静态代理和动态代理,静态代理就是代码在编译成class文件后,就已经有代理类的 ...

  9. 代理模式(静态代理、jdk动态代理、CGLib动态代理)

    目录 1.什么是代理模式? 2.静态代理 1.案例 2.优化案例 3.静态代理瓶颈 3.动态代理 1.什么是动态代理? 2.jdk动态代理 1.动态代理的工具类 匿名内部类简介 2.jdk动态代理实现 ...

最新文章

  1. 批处理修改远程桌面端口,并修改相应的防火墙配置
  2. Linux基础:调查和管理进程
  3. Flex组件的项目渲染器(ItemRenderer)使用总结
  4. 在fritzing中怎么导入_电路图制作软件(Fritzing)
  5. 【十万个编程篇】Linux—Debian系列,deb包首次分析
  6. ado.net mysql 下载_ADO.Net连接Mysql
  7. Swift学习笔记_数据类型_整数类型
  8. 动手学深度学习Pytorch Task08
  9. Zabbix 4.0.0 新功能介绍
  10. ELK官方文档收集Kibana监视数据编辑
  11. Hive的三种建表方式
  12. halcon窗体的移动和缩放_Halcon hWindowControl 鼠标缩放平移区域模板匹配绘制
  13. python文件管不了_Python文件_管道与模块编写
  14. java9类加载器_深入理解java虚拟机(九)类加载器以及双亲委派模型
  15. mysql数据库攻击与防御pdf_SQL注入攻击与防御 中文PDF清晰扫描版(38.6M)
  16. 微PE装Win10详细教程 手把手教你UEFI+GPT方式安装Win10系统教程
  17. linux查找文件重复项,Linux中如何使用命令查找重复文件
  18. python画双y轴图像
  19. 标号法(label-setting algorithm)求解带时间窗的最短路问题(ESPPRC)
  20. 头脑王者服务器维护,头脑王者请求超时怎么解决 头脑王者查询服务器失败怎么回事...

热门文章

  1. javafx_scenebuilder-2_0-windows.msi 百度云盘下载
  2. 【设计模式】(四)抽象工厂模式(Abstract Factory Pattern)
  3. 蓝桥杯_穿越雷区 java
  4. java pdf设置页面大小_Java PDF页面设置——页面大小、页边距、纸张方向、页面旋转...
  5. python图像处理第三方库mayavi_用Mayavi和Python在曲面上渲染图像
  6. java setdaemon_setDaemon的简单使用
  7. live555服务器性能,Live555 分析(二):服务端
  8. 【上新】神秘的 Gotchiverse 艺术版本来袭,将带来三个惊喜新功能!
  9. java的join方法_Javajoin方法详解
  10. matlab中怎么求立方和,急求立方和计算公式!