尽管业务委派类确实给您的企业Java设计带来了激动人心的新灵活性,但为您应用程序中的每个会话bean都编码一个业务委派还是太麻烦了。在本文向您展示如何创建业务委派类的更通用的版本:动态委派。
在前文中,我们讨论了如何用业务委派类(请不要与业务接口(BusinessInterface)模式相混淆)来访问您的EJB组件。通过在客户机代码和EJB 代码之间插入业务委派类,我们可以将应用程序的 Web层与 EJB语义和业务逻辑隔离开来。
研究这类设计的一种方法是看它有多通用。先从一个应用程序入手,该应用程序中的业务逻辑和技术函数是紧密地交织在一起的,我们已经逐步分离出应用程序的不同层,并使用不同的技术来降低它们的相互依赖。在这样做时,您应该会发现:应用程序底层结构越通用,则随着时间的推移,它就会越健壮且可维护性越好。
业务委派类:复习
LibraryDelegate 类的大部分代码只是复制了原始 Library bean的方法。LibraryDelegate添加了init() 、 destroy() 和构造器方法,然后用这些方法将任务委派给Librarybean。在这样做时,委派充当Web层和企业 bean 之间的缓冲区。这里是 原始 bean 的业务接口。
方法的繁殖
除非您考虑到多个会话 bean 有 10 个、20个或更多方法,否则这种方法的问题并不明显。实际上,找到拥有50个或更多方法的会话bean 并不罕见!因为bean的业务接口必须包括该bean的所有方法,所以业务委派类也将这样做。那会使代码过于庞大,并很容易出错。
除了庞大的代码之外,我们还必须考虑变化因素。因为 Delegate类必须复制bean的所有方法,并且随着时间推移,bean不可避免地会发生变化,您会发现需要花费很多时间来将新的方法添加到Delegate,更别提重新编译了,有可能还要测试新代码。
就其本身而言,这看起来似乎不是很严重的问题。但假如我们开始使用业务委派类来从技术基础结构(在本文是指EJB组件)中抽象业务和表示逻辑呢。如果更改远程接口需要对业务委派进行更改,那么,实际上,我们的业务委派仍然与底层组件联系在一起。
我们需要更好的方法,您说是不是。确实有更好的方法。
动态委派
解决方案是使用 动态委派,而它又使用Java反射(reflection)。您可以使委派动态地调用目标EJB组件的远程接口上的方法(通过JavaReflectionAPI),而不必将每个业务方法硬编码到委派中。这样允许彻底消除来自远程接口的耦合,因为,为bean的业务或远程接口添加方法时不需要在业务委派中进行相应更改。使用动态委派还使得更改您的技术基础结构更为容易。从远程接口和EJB技术迁移到另一种技术(如JavaData Objects,JDO)只需要更改委派的init()方法。所有其它方法调用将继续通过bean的接口进行委派,并且可以继续使用无需进一步更改。清单 1 显示了Library业务委派的动态版本:
清单 1. Library bean 的业务委派
以下是引用片段: !– Code highlighting produced byActiproCodeHighlighter(freeware) http://www.CodeHighlighter.com/ –>1 package com.ibm.library; 2 import java.lang.reflect.Method; 3 import java.lang.reflect.InvocationTargetException; 4 import java.rmi.RemoteException; 5 import java.util.HashMap; 6 import java.util.Map; 7 import javax.ejb.CreateException; 8 import javax.naming.NamingException; 9 public class LibraryDelegate implements ILibrary { 10 private ILibrary library; 11 private Map availableMethods; 12 public LibraryDelegate() { 13 init(); 14 } 15 public void init() { 16 // Look up andobtain our session bean 17 try { 18 LibraryHomelibraryHome = 19 (LibraryHome)EJBHomeFactory.getInstance().lookup( 20 java:comp/env/ejb/LibraryHome,LibraryHome.class); 21 library= libraryHome.create(); 22 //Get the methods available for use in proxying 23 availableMethods= new HashMap(); 24 Methodmethods = ILibrary.class.getMethods(); 25 for(int i=0; i 26 availableMethods.put(methods.getName(), 27 methods); 28 } 29 } catch(NamingException e) { 30 thrownew RuntimeException(e); 31 } catch(CreateException e) { 32 thrownew RuntimeException(e); 33 } catch(RemoteException e) { 34 thrownew RuntimeException(e); 35 } 36 } 37 // All the hard-codedmethods are removed 38 public Object 39 invoke(Objectproxy, Method method, Object args) 40 throwsThrowable{ 41 try { 42 //See if this is init() or destroy() 44 init(); 45 returnnull; 46 }else if (method.getName().equals(destroy)) { 47 destroy(); 48 returnnull; 49 }else { 50 Methodmethod = 51 (Method)availableMethods.get(method.getName()); 52 //See if we found anything 54 returnmethod.invoke(library, args); 55 }else { 56 thrownew 57 NoSuchMethodException(TheLibrary does not 58 supportthe method.getName() method.); 59 } 60 } 61 } catch(InvocationTargetException e) { 62 //We dont support throwing RuntimeExceptions fromEJBs 63 //directly 65 thrownew RuntimeException(e); 66 }else { 67 throwe.getTargetException(); 68 } 69 } 70 } 71 public voiddestroy() { 72 //In this case, do nothing 73 } 74 } |
动态委派出色地解决了委派、bean及其业务接口之间的耦合问题。但是,它并不是完美的解决方案,也不会总是最好的解决方案。虽然您从这种方法中获得了极大的灵活性,但也付出了性能代价。Java反射并不十分快,因此在调用invoke()和获得结果之间,您会感到一些延时。前一篇技巧文章中展示的静态业务委派类是更快的解决方案,但它使您的业务层和技术层的耦合程度比您所希望的要高。因此,在权衡这两个选择时,选择哪一个要根据设计或性能而定。当应用程序的设计比整体性能更重要时,动态委派是更好的选择。当性能是更重要的因素时,业务委派是更好的选择。
您可能会发现自己正在将动态委派用于内部网应用程序,在内部网中,所有机器都在本地网络上,并且您会经常添加或更改功能。对于电子商业和面向顾客的应用程序,原始的业务委派可能是更好的选择。在这两种情况下,您现在都应该对业务委派及其工作原理有了更好的理解。
我们一直都在努力坚持原创.......请不要一声不吭,就悄悄拿走。
我原创,你原创,我们的内容世界才会更加精彩!
【所有原创内容版权均属TechTarget,欢迎大家转发分享。但未经授权,严禁任何媒体(平面媒体、网络媒体、自媒体等)以及微信公众号复制、转载、摘编或以其他方式进行使用。】
微信公众号
TechTarget
官方微博
TechTarget中国
作者
相关推荐
-
内存数据网格提供商一头扎进Java
10年的时间里,应用性能解决方案提供商Alachisoft一直在用NCache(针对N-Tier和网格计算.NET应用的内存计算和数据网格产品)为.NET社区服务。
-
遇到这样一个问题:通过java service wrapper部署应用,wrapper进程占用的内存会一直升高, 直到把内存吃完应用崩溃,但是这个wrapper
遇到这样一个问题:通过java service wrapper部署应用,wrapper进程占用的内存会一直升高 […]
-
Google App Engine for Java 对于目前中国需要学习吗?
-
前无古人后无来者的Java平台
开发人员一直在致力于保持Java的活力,经过20年后,我们感觉从来没有更好的、更令人激动的时刻如同Java社区一样。