a我考网

 找回密码
 立即注册

QQ登录

只需一步,快速开始

扫一扫,访问微社区

查看: 190|回复: 0

[基础知识] Java实践之用动态代理进行修饰

[复制链接]
发表于 2012-8-4 12:37:27 | 显示全部楼层 |阅读模式
动态代办代庖工具 是 java.lang.reflect 包的一部门,在 JDK 1.3 版本中添加到 JDK,它许可轨范建树代办代庖对象,代办代庖对象能实现一个或多个已知接口,并用反射庖代内置的虚体例分拨,编程地分拨对接口体例的挪用。这个过程许可实现“进取”体例挪用,年夜头路由它们或者动态地添加功能。   动态代办代庖为实现良多常见设计模式(搜罗 Facade、Bridge、Interceptor、Decorator、Proxy(搜罗远程和虚拟代办代庖)和 Adapter 模式)供给了替代的动态机制。虽然这些模式不使用动态代办代庖,只用通俗的类就能够实现,可是在良多情形下,动态代办代庖体例更便利、更紧凑,可以断根良多手写或生成的类。
/ ]2 i! U, l) }  h( v7 w( j9 JProxy模式
; m7 m- R, T( f  H( h  Proxy 模式中要建树“stub”或“surrogate”对象,它们的目的是接管请求并把请求转发到现实执行工作的其他对象。远程体例挪用(RMI)操作 Proxy 模式,使得在其他 JVM 中执行的对象就像当地对象一样;企业 JavaBeans (EJB)操作 Proxy 模式添加远程挪用、平安性和事务分界;而 JAX-RPC Web 处事则用 Proxy 模式让远程处事默示得像当地对象一样。在每一种情形中,潜在的远程对象的行为是由接口界说的,而接口素质上接管多种实现。挪用者(在年夜年夜都情形下)不能区扶持它们只是持有一个对 stub 而不是现实对象的引用,因为二者实现了不异的接口;stub 的工作是查找现实的对象、封送参数、把参数发送给现实对象、解除仿胪返回值、把返回值返回给挪用者。代办代庖可以用来供给远程节制(就像在 RMI、EJB 和 JAX-RPC 中那样),用平安性策略包装对象(EJB)、为昂贵的对象(EJB 实体 Bean)供给惰性装入,或者添加检测工具(例如日志记实)。
  [0 l; b- @/ l  在 5.0 以前的 JDK 中,RMI stub(以及它对等的 skeleton)是在编译时由 RMI 编译器(rmic)生成的类,RMI 编译器是 JDK 工具集的一部门。对于每个远程接口,城市生成一个 stub(代办代庖)类,它代表远程对象,还生成一个 skeleton 对象,它在远程 JVM 中做与 stub 相反的工作 —— 解除封送参数并挪用现实的对象。近似地,用于 Web 处事的 JAX-RPC 工具也为远程 Web 处事生成代办代庖类,年夜而使远程 Web 处事看起来就像当地对象一样。
' E! o$ I6 `$ N% d/ Z! G  不管 stub 类是以源代码仍是以字节码生成的,代码生成仍然会向编译过程添加一些额外轨范,而且因为命名相似的类的泛滥,会带来意义恍惚的可能性。另一方面,动态代办代庖机制撑持在编译时没有生成 stub 类的情形下,在运行时建树代办代庖对象。在 JDK 5.0 及往后版本中,RMI 工具使用动态代办代庖庖代了生成的 stub,结不美观 RMI 变得更轻易使用。良多 J2EE 容器也使用动态代办代糊弄实现 EJB。EJB 手艺严重地依靠使用阻挡(interception)来实现平安性和事务分界;冻┈代办代庖为接口上挪用的所有体例供给了集中的节制流程路径。0 R4 k9 x& y9 E/ X# |
动态代办代庖机制
/ W' {) G- j5 K5 _6 T  动态代办代庖机制的焦点是 InvocationHandler 接口,如清单 1 所示。挪用句柄的工作是代表动态代办代庖现实执行所请求的体例挪用。传递给挪用句柄一个 Method 对象(年夜 java.lang.reflect 包),参数列表则传递给体例;在最简单的情形下,可能仅仅是挪用反射性的体例 Method.invoke() 并返回结不美观。
( v# ?3 ^  l3 N8 d/ `" B/ k: s  清单 1. InvocationHandler 接口
! q7 R) o+ @/ Q5 [# T  public interface InvocationHandler { Object invoke(Object proxy, Method method, Object[] args) throws Throwable; }
* {0 L6 ]1 I6 K7 E' h, _. N9 d' f  每个代办代庖都有一个与之联系关系的挪用句柄,只要代办代庖的体例被挪用时就会挪用该句柄。按照通用的设计原则:接口界说类型、类界说实现,代办代庖对象可以实现一个或多个接口,可是不能实现类。因为代办代庖类没有可以访谒的名称,它们不能有机关函数,所以它们必需由工场建树。清单 2 显示了动态代办代庖的最简单的可能实现,它实现 Set 接口并把所有 Set 体例(以及所有 Object 体例)分拨给封装的 Set 实例。, K+ B7 d, M: c; e+ {: |8 M' @1 u
  清单 2. 包装 Set 的简单的动态代办代庖' X0 [$ t2 p  {9 N  n
  public class SetProxyFactory { public static Set getSetProxy(final Set s) { return (Set) Proxy.newProxyInstance (s.getClass().getClassLoader(), new Class[] { Set.class }, new InvocationHandler() { public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { return method.invoke(s, args); } }); } }9 Q8 i8 z1 m5 D' s' F- `" ]
  SetProxyFactory 类包含一个静态工场体例 getSetProxy(),它返回一个实现了 Set 的动态代办代庖。代办代庖对象现实实现 Set —— 挪用者无法区分(除非经由过程反射)返回的对象是动态代办代庖。SetProxyFactory 返回的代办代庖只做一件事,把体例分拨给传递给工场体例的 Set 实例。虽然反射代码凡是斗劲难读,可是这里的内容很少,跟上节制流程并不难 —— 只要某个体例在 Set 代办代庖上被挪用,它就被分拨给挪用句柄,挪用句柄只是反射地挪用底层包装的对象上的方针体例。当然,绝对什么都不做的代办代庖可能有点傻,是不是呢?
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

Archiver|手机版|小黑屋|Woexam.Com ( 湘ICP备18023104号 )

GMT+8, 2024-5-7 11:26 , Processed in 0.171457 second(s), 21 queries .

Powered by Discuz! X3.4 Licensed

© 2001-2017 Comsenz Inc.

快速回复 返回顶部 返回列表