分享
 
 
 

在EJB环境中实现“观察者”模式

王朝other·作者佚名  2008-05-31
窄屏简体版  字體: |||超大  

在EJB环境中实现“观察者”模式

Observer模式(“观察者”模式)或许是降低对象结合程度的最佳方法之一。例如,在编写一个典型的应用程序时,你可能决定提供一个工厂或治理器触发适当的事件,以这些事件的一组监听器的形式提供分离的业务逻辑;此后,系统的启动类就在工厂或者治理器创建完毕之后,把这些监听器关联到工厂或者治理器。

在大多数J2EE系统中,这种工厂/治理器都是无状态的会话Bean。EJB容器处理对无状态会话Bean的请求,根据请求创建无状态会话Bean的实例,或重用现有的实例。问题在于,每次初始化一个新的Bean实例时都必须伴有一组监听器,这组监听器和为其他实例而运行的监听器完全相同。合理的方案应该是,当一个无状态会话Bean实例被创建的时候,它访问某个知识库,通过一定的方法获知相关的监听器,然后建立和这些监听器的关系。在这篇文章中,我要介绍的就是如何实现这一方案。

一种典型的情形

请考虑下面这种典型的情形。一个在线拍卖系统有一个无状态会话Bean,名为AUCtionFactory,这个Bean创建拍卖(auction)对象。对于每一个新创建的拍卖对象,业务逻辑要求系统执行一些附加的操作,比如发送email、更新用户摘要文件,等等。在许多系统上,创建拍卖对象和执行这些附加操作的代码如下所示:

public Auction createAuction(int numOfContainers) throws RemoteException{ SomeAuctionClass auction = new SomeAuctionClass (numOfContainers); // 创建拍卖对象之后,接下来要编写下面这种执行附加操作的代码 //(而不是简单地发送一个“拍卖对象已经创建”的事件) sendEmailsAboutNewAuction(auction); updateUserProfiles(auction); doOtherNotificationStuffAboutNewAuction(auction); //等等.... return auction;}

之所以要编写这种质量很差的代码,原因就在于初始化各个Bean实例时附带一组必需的监听器很困难。假如这个Bean是一个事件发布者,而且每一个Bean实例初始化的时候都带有一组它需要的监听器,上述代码可以变得更简洁、更强壮,例如:

public Auction createAuction(int numOfContainers) throws RemoteException{ SomeAuctionClass auction = new SomeAuctionClass (numOfContainers); fireAuctionCreated(auction); return auction;}

基本原理说明

实现本文技巧的基本原理其实很简单。一个ListenerRegistry类实现事件发布者类和必须关联到该类的监听器之间的映射。系统的启动模块初始化ListenerRegistry,为每一种发布者类型初始化一组必需的监听器。当发布者被创建或激活,它就访问ListenerRegistry,把它的类传递给ListenerRegistry,获得一组监听器。然后,发布者把所有这些监听器关联到自身。就这么简单。

你也许会很自然地问,“什么是ListenerSupplier?”和“为什么不直接注册和使用EventListener?”确实可以;事实上,该框架的第一个版本就是直接使用事件监听器。但是,假如在ListenerRegistry中使用监听器,这些监听器必须在注册的时候就存在。另一方面,假如注册的是一个“中介者”ListenerSupplier(监听器提供者),你就可以自由地把创建/提取监听器延迟到它绝对必需的时候。ListenerSupplier类似于工厂,但两者的不同之处在于,ListenerSupplier并非必定要创建新的监听器,它的目标是返回监听器。每次getListener()方法被调用时,ListenerSupplier是创建一个新的监听器,还是每次都返回同一实例,这一切由开发者自己决定。

因此,结合运用ListenerRegistry和监听器提供者,我们可以在事件发布者和观察者(或监听器)不存在的情况下,建立两者之间的关系。可以认为,这个优点很重要,它延迟了发布者和观察者的实例化。

具体实现

在这一部分,你将看到整个框架中所有组成部分的实现代码。我假定你已经了解必要的基础知识,比如EJB、同步,当然还有Java核心库。完整的源代码可以从本文最后下载。

下面是ListenerRegistry接口的代码:

//ListenerRegistry.javapackage com.jwASP.listener;import java.util.EventListener;import java.rmi.RemoteException;import com.jwasp.listener.ListenerSupplier;/*** 框架的核心。实现事件发布者类和监听器提供者之间的映射*/public interface ListenerRegistry {void addListenerSupplier(ListenerSupplier listenerSupplier, Class publisherClass);void removeListenerSupplier(ListenerSupplier listenerSupplier, Class publisherClass);EventListener[] getListeners(Class publisherClass) throws RemoteException, ListenerActivationException;}

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有