首页 | 新闻 | 新品 | 文库 | 方案 | 视频 | 下载 | 商城 | 开发板 | 数据中心 | 座谈新版 | 培训 | 工具 | 博客 | 论坛 | 百科 | GEC | 活动 | 主题月 | 电子展
返回列表 回复 发帖

Observer模式在J2EE中的实现(2)

Observer模式在J2EE中的实现(2)

值传递还是远程引用传递?值传递:
在Java RMI中要求所有的参数和返回类型是JAVA的基本类型或实现Java.io.Serilizable的对象。串行化对象通过值传递(又名拷贝传递),而不是引用传递,这意味着在某一层中串行化对象的更并不自动影响到其它的对象。      
远程引用传递:
对于EJB对象而言,它由两个接口(home接口和remote接口)和一个类组成。容器会根据ejb规范来生成实现上面两个接口的类(我们分别称为xxxEJBHome对象和xxxEjbObject对象)。在较多的容器的实现方案中,xxxEJBHome对象使用了factory模式来创建xxxEjbObject对象;xxxEjbObject对象则采用proxy模式,作为xxxBean的代理类。在生成以上两个对象的同时,容器会从部署文件中读取关于安全、事务、持久性等服务并在xxxEjbObject对象和xxxEJBHome对象中添加以上服务的代码。而且xxxEJBHome对象和xxxEjbObject对象都是分布式对象,我们在此只讨论xxxEjbObject对象。所谓分布式对象,从本质上来讲,分为3个部分:object server、skeleton、stub。其中object server和skeleton位于服务器端,而stub位于客户端。Object server负责实现业务逻辑,skeleton负责marshal和unmarshal方法签名。      
图二:分布式对象显然,EJB的客户(调用EJB的对象)可以是任何对象,包括EJB和一般的Java类甚至是用任何语言写的corba客户端。
从EJB的客户视角来看的话,我们只能看到一个home接口、一个remote接口(对于实体bean的话,还可以看见一个主键类,而bean类对客户是不可见的)。但我们从上面的论述,我们可以知道,对于remote接口中地方法调用,实际上是多态地调用XXX_Stub类。即XXX_Stub对象对客户具有可见性(但这种可见性是透明的,即客户不知道这种可见性的存在)。由于,XXX_Stub对象和Object Server实现了相同的接口,并且Object server真正实现了业务逻辑。所以,当在客户端调用XXX_Stub对象的方法时候,XXX_Stub对象通过socket通信机制将方法签名传给XXX_Skeleton对象,XXX_Skeleton对象在去委托Object Server完成业务处理逻辑。因此,Object Server本身发生了改变。我们称XXX_Stub对象是Object Server对象的远程引用,并认为当分布式对象作为参数传递的时候,是通过引用传递的(会产生副作用�D�D即改变参数对象),只不过这种引用是远程引用。可以参见本文的示范代码,了解远程引用。
在J2EE中实现Observer模式的典型错误为了说明问题,我们从一个简单例子开始着手:假设一个或多个位于web tier层的、可以序列化(serilizable)的Java类,想要从位于EJB tier层的一个或多个实体bean中获取数据(它们可能是分布在不同EJB SERVER中)。可以把web tier层的Java类看成是一个分布式异构数据源的联合视图。显然,它们之间存在着依赖关系,而且这两个方面要相互独立(位于不同的tier),并且当一个对象改变的同时,不知道具体又多少个对象有待改变。因此,我们决定用OBSERVER模式来实现这个问题。把bean作为observer,把Entity Bean作为Subject。参照图三Observer设计模式
图三:Observer设计模式这样,就会使起observer作用的Java类对起subject作用的entity bean中具有参数可见性,而且由于它们可以位于不同的机器上,所有我们要为Java类实现serilizable接口,从而使它可以在网络上传递。看上去似乎非常完美,但不幸的是:在运行的时候,我们发现客户端并不能自动更新。究其原因,我们发现,原来Java类是通过值传递的,即entity bean中有一个Java类的拷贝,它对拷贝进行修改,但不会影响原来的Java类。
但如果我们在另外一种情况下,把entity bean作为observer,而使Java类作为subject,由于Java类拥有entity bean的远程引用,当subject产生事件的时候,会通知entity bean的远程引用作相应的改动。此时与Java类位于不同tier的entity bean的发生了真正的改动,从而实现了事件通知范型的observer模式。另外,为了使observer可以观察多个subject,entity bean要拥有observer对象,而这些observer对象(Java类)通过值传递被序列化到entity bean中,而且这种序列化是深度序列化。由于observer只是准备从subject中提取数据,而不是改变subject的数据,所有这时候的值传递是可行的。但是,由于EJB规范的要求,所有商务方法都要抛出java.rmi.RemoteException,所以单纯的从java类库提供的Observer接口继承是不行的。具体的细节可以参见ejb observer pattern文档(参考 )。      
注意:文档中的附带程序在JB5.0+BAS4.5中会出现corba marshal的问题,如果你只是为了实现一个subject对应多个observer,而且是subject将所有的数据推给observer的话,可以将EJBObserver接口中的update(EJBObservable observable,Object args)改为update(EJBObservable observable,Object args),这样可以使程序在JB5.0+BAS4.5集成运行环境中通过。
返回列表