仓酷云

 找回密码
 立即注册
搜索
热搜: 活动 交友 discuz
查看: 685|回复: 14
打印 上一主题 下一主题

[学习教程] JAVA网页设计Java 实际与理论: 用静态代办署理举行润色仓酷云

[复制链接]
飘灵儿 该用户已被删除
跳转到指定楼层
楼主
发表于 2015-1-18 11:29:30 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有帐号?立即注册

x
java是一种面向对象的编程语言,优点是可移植性比较高,最初设计时就是本着一次编写到处执行设计的。可以开发各种应用程序和游戏,不过速度没有c++快,所以一般是不用java来编写应用程序和电脑游戏。简介:静态代办署理工具是java.lang.reflect包的一部分,在JDK1.3版本中增加到JDK,它同意程序创立代办署理对象,代办署理对象能完成一个或多个已知接口,并用反射取代内置的虚办法分拨,编程地分拨对接口办法的挪用。这个历程同意完成“截取”办法挪用,从头路由它们大概静态地增加功效。本期文章中,BrianGoetz先容了几个用于静态代办署理的使用程序。
静态代办署理为完成很多罕见计划形式(包含Facade、Bridge、Interceptor、Decorator、Proxy(包含远程和假造代办署理)和Adapter形式)供应了替换的静态机制。固然这些形式不利用静态代办署理,只用一般的类就可以够完成,可是在很多情形下,静态代办署理体例更便利、更松散,能够扫除很多手写或天生的类。
Proxy形式
Proxy形式中要创立“stub”或“surrogate”对象,它们的目标是承受哀求并把哀求转发到实践实行事情的其他对象。远程办法挪用(RMI)使用Proxy形式,使得在其他JVM中实行的对象就像当地对象一样;企业JavaBeans(EJB)使用Proxy形式增加远程挪用、平安性和事件分界;而JAX-RPCWeb服务则用Proxy形式让远程服务体现得像当地对象一样。在每种情形中,潜伏的远程对象的举动是由接口界说的,而接口实质上承受多种完成。挪用者(在年夜多半情形下)不克不及辨别出它们只是持有一个对stub而不是实践对象的援用,由于两者完成了不异的接口;stub的事情是查找实践的对象、封送参数、把参数发送给实践对象、排除封送前往值、把前往值前往给挪用者。代办署理能够用来供应远程把持(就像在RMI、EJB和JAX-RPC中那样),用平安性战略包装对象(EJB)、为高贵的对象(EJB实体Bean)供应惰性装进,大概增加检测工具(比方日记纪录)。
在5.0之前的JDK中,RMIstub(和它对等的skeleton)是在编译时由RMI编译器(rmic)天生的类,RMI编译器是JDK工具集的一部分。关于每一个远程接口,城市天生一个stub(代办署理)类,它代表远程对象,还天生一个skeleton对象,它在远程JVM中做与stub相反的事情——排除封送参数并挪用实践的对象。相似地,用于Web服务的JAX-RPC工具也为远程Web服务天生代办署理类,从而使远程Web服务看起来就像当地对象一样。
不论stub类是以源代码仍是以字节码天生的,代码天生仍旧会向编译历程增加一些分外步骤,并且由于定名类似的类的众多,会带来意义含混的大概性。另外一方面,静态代办署理机制撑持在编译时没有天生stub类的情形下,在运转时创立代办署理对象。在JDK5.0及今后版本中,RMI工具利用静态代办署理取代了天生的stub,了局RMI变得更简单利用。很多J2EE容器也利用静态代办署理来完成EJB。EJB手艺严峻地依托利用拦阻(interception)来完成平安性和事件分界;静态代办署理为接口上挪用的一切办法供应了会合的把持流程路径。

回页首
静态代办署理机制
静态代办署理机制的中心是InvocationHandler接口,如清单1所示。挪用句柄的事情是代表静态代办署理实践实行所哀求的办法挪用。传送给挪用句柄一个Method对象(从java.lang.reflect包),参数列表则传送给办法;在最复杂的情形下,大概仅仅是挪用反射性的办法Method.invoke()并前往了局。
清单1.InvocationHandler接口
  1. publicinterfaceInvocationHandler{Objectinvoke(Objectproxy,Methodmethod,Object[]args)throwsThrowable;}
复制代码
每一个代办署理都有一个与之联系关系的挪用句柄,只需代办署理的办法被挪用时就会挪用该句柄。依据通用的计划准绳:接口界说范例、类界说完成,代办署理对象能够完成一个或多个接口,可是不克不及完成类。由于代办署理类没有能够会见的称号,它们不克不及有机关函数,以是它们必需由工场创立。清单2显现了静态代办署理的最复杂的大概完成,它完成Set接口并把一切Set办法(和一切Object办法)分拨给封装的Set实例。
清单2.包装Set的复杂的静态代办署理
  1. publicclassSetProxyFactory{publicstaticSetgetSetProxy(finalSets){return(Set)Proxy.newProxyInstance(s.getClass().getClassLoader(),newClass[]{Set.class},newInvocationHandler(){publicObjectinvoke(Objectproxy,Methodmethod,Object[]args)throwsThrowable{returnmethod.invoke(s,args);}});}}
复制代码
SetProxyFactory类包括一个静态工场办法getSetProxy(),它前往一个完成了Set的静态代办署理。代办署理对象实践完成Set——挪用者没法辨别(除非经由过程反射)前往的对象是静态代办署理。SetProxyFactory前往的代办署理只做一件事,把办法分拨给传送给工场办法的Set实例。固然反射代码一般对照难读,可是这里的内容很少,跟上把持流程其实不难——只需某个办法在Set代办署理上被挪用,它就被分拨给挪用句柄,挪用句柄只是反射地挪用底层包装的对象上的方针办法。固然,相对甚么都不做的代办署理大概有点傻,是否是呢?
甚么都不做的适配器
关于像SetProxyFactory如许甚么都不做的包装器来讲,实践有个很好的使用——能够用它平安地把对象援用的局限减少到特定接口(或接口集)上,体例是,挪用者不克不及提拔援用的范例,使得能够更平安地把对象援用传送给不受信托的代码(比方插件或回调)。清单3包括一组类界说,完成了典范的回调场景。从中会看到静态代办署理能够更便利地替换一般用手工(或用IDE供应的代码天生导游)完成的Adapter形式。
清单3.典范的回调场景
  1. publicinterfaceServiceCallback{publicvoiddoCallback();}publicinterfaceService{publicvoidserviceMethod(ServiceCallbackcallback);}publicclassServiceConsumerimplementsServiceCallback{privateServiceservice;...publicvoidsomeMethod(){...service.serviceMethod(this);}}
复制代码
ServiceConsumer类完成了ServiceCallback(这一般是撑持回调的一个便利路子)并把this援用传送给serviceMethod()作为回调援用。这类办法的成绩是没无机制能够制止Service完成把ServiceCallback提拔为ServiceConsumer,并挪用ServiceConsumer不但愿Service挪用的办法。偶然对这个风险其实不体贴——但偶然却体贴。假如体贴,那末能够把回调对象作为外部类,大概编写一个甚么都不做的适配器类(请参阅清单4中的ServiceCallbackAdapter)并用ServiceCallbackAdapter包装ServiceConsumer。ServiceCallbackAdapter避免Service把ServiceCallback提拔为ServiceConsumer。
清单4.用于平安地把对象限定在一个接口上以便不被歹意代码不克不及的适配器类
  1. publicclassServiceCallbackAdapterimplementsServiceCallback{privatefinalServiceCallbackcb;publicServiceCallbackAdapter(ServiceCallbackcb){this.cb=cb;}publicvoiddoCallback(){cb.doCallback();}}
复制代码
编写ServiceCallbackAdapter如许的适配器类复杂却有趣。必需为包装的接口中的每一个办法编写重定向类。在ServiceCallback的示例中,只要一个必要完成的办法,可是某些接口,比方Collections或JDBC接口,则包括很多办法。古代的IDE供应了“DelegateMethods”导游,下降了编写适配器类的事情量,可是仍旧必需为每一个想要包装的接口编写一个适配器类,并且关于只包括天生的代码的类,也有一些让人不中意的中央。看起来应该有一种体例能够更松散地暗示“甚么也不做的限定适配器形式”。
通用适配器类
清单2中的SetProxyFactory类固然比用于Set的等价的适配器类更松散,可是它仍旧只合用于一个接口:Set。可是经由过程利用泛型,能够简单地创立通用的代办署理工场,由它为任何接口做一样的事情,如清单5所示。它几近与SetProxyFactory不异,可是能够合用于任何接口。如今不再用编写限定适配器类了!假如想创立代办署理对象平安地把对象限定在接口T,只需挪用getProxy(T.class,object)就能够了,不必要一堆适配器类的分外包袱。
清单5.通用的限定适配器工场类
  1. publicclassGenericProxyFactory{publicstatic<T>TgetProxy(Class<T>intf,finalTobj){return(T)Proxy.newProxyInstance(obj.getClass().getClassLoader(),newClass[]{intf},newInvocationHandler(){publicObjectinvoke(Objectproxy,Methodmethod,Object[]args)throwsThrowable{returnmethod.invoke(obj,args);}});}}
复制代码

回页首
静态代办署理作为Decorator
固然,静态代办署理工具能做的,远不单单是把对象范例限定在特定接口上。从清单2和清单5中复杂的限定适配器到Decorator形式,是一个小的奔腾,在Decorator形式中,代办署理用分外的功效(比方平安检测或日记纪录)包装挪用。清单6显现了一个日记InvocationHandler,它在挪用方针对象上的办法以外,还写进一条日记信息,显现被挪用的办法、传送的参数,和前往值。除反射性的invoke()挪用以外,这里的全体代码只是天生调试信息的一部分——还不是太多。代办署理工场办法的代码几近与GenericProxyFactory不异,区分在于它利用的是LoggingInvocationHandler而不是匿名的挪用句柄。
清单6.基于代办署理的Decorator,为每一个办法挪用天生调试日记
  1. privatestaticclassLoggingInvocationHandler<T>implementsInvocationHandler{finalTunderlying;publicLoggingHandler(Tunderlying){this.underlying=underlying;}publicObjectinvoke(Objectproxy,Methodmethod,Object[]args)throwsThrowable{StringBuffersb=newStringBuffer();sb.append(method.getName());sb.append("(");for(inti=0;args!=null&&i<args.length;i++){if(i!=0)sb.append(",");sb.append(args[i]);}sb.append(")");Objectret=method.invoke(underlying,args);if(ret!=null){sb.append("->");sb.append(ret);}System.out.println(sb);returnret;}}
复制代码
假如用日记代办署理包装HashSet,并实行上面这个复杂的测试程序:
  1. Sets=newLoggingProxy(Set.class,newHashSet());s.add("three");if(!s.contains("four"))s.add("four");System.out.println(s);
复制代码
会失掉以下输入:
  1. add(three)->truecontains(four)->falseadd(four)->truetoString()->[four,three][four,three]
复制代码
这类体例是给对象增加调试包装器的一种好的并且简单的体例。它固然比天生代办署理类并手工创立大批println()语句简单很多(也更通用)。我进一步改善了这一办法;不用无前提地天生调试输入,相反,代办署理能够查询静态设置存储(从设置文件初始化,能够由JMXMBean静态修正),断定是不是必要天生调试语句,乃至大概在逐一类或逐一实例的基本长进行。
在这一点上,我以为读者中的AOP喜好者们几近要跳出来讲“这恰是AOP善于的啊!”是的,可是办理成绩的办法不止一种——仅仅由于某项手艺能办理某个成绩,其实不意味着它就是最好的办理计划。在任何情形下,静态代办署理体例都有完整在“纯Java”局限内事情的上风,不是每一个公司都用(或应该用)AOP的。
静态代办署理作为适配器
代办署理也能够用作真实的适配器,供应了对象的一个视图,导出与底层对象完成的接口分歧的接口。挪用句柄不必要把每一个办法挪用都分拨给不异的底层对象;它能够反省称号,并把分歧的办法分拨给分歧的对象。比方,假定有一组暗示耐久实体(Person、Company和PurchaseOrder)的JavaBean接口,指定了属性的getter和setter,并且正在编写一个耐久层,把数据库纪录映照到完成这些接口的对象上。如今不必为每一个接口编写或天生类,能够只用一个JavaBean作风的通用代办署理类,把属性保留在Map中。
清单7显现的静态代办署理反省被挪用办法的称号,并经由过程查询或修正属性图间接完成getter和setter办法。如今,这一个代办署理类就可以完成多个JavaBean作风接口的对象。
清单7.用于把getter和setter分拨给Map的静态代办署理类
  1. publicclassJavaBeanProxyFactory{privatestaticclassJavaBeanProxyimplementsInvocationHandler{Map<String,Object>properties=newHashMap<String,Object>();publicJavaBeanProxy(Map<String,Object>properties){this.properties.putAll(properties);}publicObjectinvoke(Objectproxy,Methodmethod,Object[]args)throwsThrowable{Stringmeth=method.getName();if(meth.startsWith("get")){Stringprop=meth.substring(3);Objecto=properties.get(prop);if(o!=null&&!method.getReturnType().isInstance(o))thrownewClassCastException(o.getClass().getName()+"isnota"+method.getReturnType().getName());returno;}elseif(meth.startsWith("set")){//Dispatchsetterssimilarly}elseif(meth.startsWith("is")){//Alternateversionofgetforbooleanproperties}else{//Candispatchnonget/set/ismethodsasdesired}}}publicstatic<T>TgetProxy(Class<T>intf,Map<String,Object>values){return(T)Proxy.newProxyInstance(JavaBeanProxyFactory.class.getClassLoader(),newClass[]{intf},newJavaBeanProxy(values));}}
复制代码
固然由于反射在Object上事情会有潜伏的范例平安性上的丧失,可是,JavaBeanProxyFactory中的getter处置会举行一些需要的分外的范例检测,就像我在这里用isInstance()对getter举行的检测一样。

回页首
功能本钱
正如已看到的,静态代办署理具有简化大批代码的潜力——不但能替换很多天生的代码,并且一个代办署理类还能取代多个手写的类或天生的代码。甚么是本钱呢?由于反射地分拨办法而不是接纳内置的虚办法分拨,大概有一些功能上的本钱。在初期的JDK中,反射的功能很差(就像初期JDK中几近其他每件事的功能一样),可是在近10年,反射已变得快多了。
不用进进基准测试机关的主题,我编写了一个复杂的、不太迷信的测试程序,它轮回地把数据添补到Set,随机地对Set举行拔出、查询和删除元素。我用三个Set完成运转它:一个未经润色的HashSet,一个手写的、只是把一切办法转发究竟层的HashSet的Set适配器,另有一个基于代办署理的、也只是把一切办法转发究竟层HashSet的Set适配器。每次轮回迭代都天生多少随机数,并实行一个或多个Set操纵。手写的适配器比起原始的HashSet只发生很少百分比的功能负荷(也许是由于JVM级无效的内联缓冲和硬件级的分支展望);代办署理适配器则分明比原始HashSet慢,可是开支要少于两个量级。
我从这个实验得出的结论是:关于年夜多半情形,代办署理体例即便对轻量级办法也实行得充足好,而跟着被代办署理的操纵变得愈来愈分量级(比方远程办法挪用,大概利用序列化、实行IO大概从数据库检索数据的办法),代办署理开支就会无效地靠近于0。固然也存在一些代办署理体例的功能开支没法承受的情形,可是这些一般只是多数情形。

回页首
停止语
静态代办署理是壮大而未充实使用的工具,能够用于完成很多计划形式,包含Proxy、Decorator和Adapter。这些形式基于代办署理的完成简单编写,更难堕落,而且具有更好的通用性;在很多情形下,一个静态代办署理类能够充任一切接口的Decorator或Proxy,如许就不必每一个接口都编写一个静态类。除最存眷功能的使用程序以外,静态代办署理体例大概比手写或呆板天生stub的体例更可取。
参考材料
进修


  • “ObjectAdapterbasedonDynamicProxy”(HeinzKabutz,ArtimaDeveloper,2005年5月):研讨利用静态代办署理完成罕见计划形式。


  • “EJBbestpractices:Thelimitsofdelegation”(BrettMcLaughlin,developerWorks,2002年12月):进修静态代办署理怎样简化营业代办署理形式的利用。


  • “用JSR-109机关可互操纵的Web服务”(JeffreyLiu和YenLu,developerWorks,2003年8月):进修JSR-109怎样撑持利用静态代办署理暗示Web服务端点,简化Web服务开辟。


  • Java实际与理论:BrianGoetz完全系列。


取得产物和手艺


  • JProxyJavadoc:JProxy类的细节息争释。


关于作者
BrianGoetz作为专业的软件开辟职员已凌驾18年了。他是Quiotix的首席参谋,这是一家软件开辟和征询公司,位于加州LosAltos。他还在多个JCP专家组效率。

Java编译的是字节码,跟C++相反,启动不够快,效率不够高,难以精确控制内存,但是优点是编程比C++容易,代码比较安全但是容易留下性能隐患,跨平台靠字节码在各个平台复制(一处编译到处调试)
因胸联盟 该用户已被删除
沙发
发表于 2015-1-21 07:48:34 | 只看该作者
Java 编程语言的风格十分接近C、C++语言。
透明 该用户已被删除
板凳
发表于 2015-1-24 05:28:19 | 只看该作者
一直感觉JAVA很大,很杂,找不到学习方向,前两天在网上找到了这篇文章,感觉不错,给没有方向的我指了一个方向,先不管对不对,做下来再说。
兰色精灵 该用户已被删除
地板
发表于 2015-1-31 21:04:43 | 只看该作者
Java 编程语言的风格十分接近C、C++语言。
深爱那片海 该用户已被删除
5#
发表于 2015-2-5 20:26:28 | 只看该作者
在全球云计算和移动互联网的产业环境下,Java更具备了显著优势和广阔前景。
爱飞 该用户已被删除
6#
发表于 2015-2-5 21:27:54 | 只看该作者
Pet Store.(宠物店)是SUN公司为了演示其J2EE编程规范而推出的开放源码的程序,应该很具有权威性,想学J2EE和EJB的朋友不要 错过了。
金色的骷髅 该用户已被删除
7#
发表于 2015-2-6 20:43:12 | 只看该作者
你现在最缺的是实际的工作经验,而不是书本上那些凭空想出来的程序。
山那边是海 该用户已被删除
8#
发表于 2015-2-8 11:36:30 | 只看该作者
是一种使网页(Web Page)由静态(Static)转变为动态(Dynamic)的语言
只想知道 该用户已被删除
9#
发表于 2015-2-25 10:31:12 | 只看该作者
是一种语言,用以产生「小应用程序(Applet(s))
若相依 该用户已被删除
10#
发表于 2015-2-26 11:41:12 | 只看该作者
我大二,Java也只学了一年,觉得还是看thinking in java好,有能力的话看英文原版(中文版翻的不怎么好),还能提高英文文档阅读能力。
简单生活 该用户已被删除
11#
发表于 2015-3-4 02:40:32 | 只看该作者
设计模式是高级程序员真正掌握面向对象核心思想的必修课。设计模式并不是一种具体"技术",它讲述的是思想,它不仅仅展示了接口或抽象类在实际案例中的灵活应用和智慧
莫相离 该用户已被删除
12#
发表于 2015-3-8 21:32:23 | 只看该作者
不过,每次的执行编译后的字节码需要消耗一定的时间,这同时也在一定程度上降低了 Java 程序的运行效率。
小女巫 该用户已被删除
13#
发表于 2015-3-12 19:02:35 | 只看该作者
我大二,Java也只学了一年,觉得还是看thinking in java好,有能力的话看英文原版(中文版翻的不怎么好),还能提高英文文档阅读能力。
乐观 该用户已被删除
14#
发表于 2015-3-13 00:22:34 | 只看该作者
接着就是EJB了,EJB就是Enterprise JavaBean, 看名字好象它是Javabean,可是它和Javabean还是有区别的。它是一个体系结构,你可以搭建更安全、更稳定的企业应用。它的大量代码已由中间件(也就是我们常听到的 Weblogic,Websphere这些J2EE服务器)完成了,所以我们要做的程序代码量很少,大部分工作都在设计和配置中间件上。
老尸 该用户已被删除
15#
发表于 2015-4-7 12:48:12 | 只看该作者
其实说这种话的人就如当年小日本号称“三个月拿下中国”一样大言不惭。不是Tomjava泼你冷水,你现在只是学到了Java的骨架,却还没有学到Java的精髓。接下来你得研究设计模式了。
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|Archiver|手机版|仓酷云 鄂ICP备14007578号-2

GMT+8, 2025-3-12 23:24

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

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