在EJB环境中实现“观察者”模式
/**
* 返回一个为指定发布者类注册的EventListener的数组。如果注册
* 器包含为该发布者注册的监听器提供者,它将依次访问每一个提供
* 者,调用其ListenerSupplier.getListener(publisherClass)方法。
* @param publisherClass发布者类
* @返回EventListener的数组
*/
public EventListener[] getListeners(Class publisherClass)
throws RemoteException,ListenerActivationException {
//如最后一个参数设置成false,则禁止继承检查
Collection listenerSuppliers = getListenerSuppliersCopy(publisherClass, true);
EventListener[] array = new EventListener[listenerSuppliers.size()];
Iterator i = listenerSuppliers.iterator();
int count = 0;
while (i.hasNext()){
ListenerSupplier listenerSupplier = (ListenerSupplier)i.next();
array[count] = listenerSupplier.getListener(publisherClass);
count++;
}
return array;
}
/**
* 返回当前已经为指定发布者类注册的监听器提供者副本。
* 这是一个同步方法,从而允许getListeners方法保持非同
* 步。
* @param publisherClass
* @param checkInheritance 如为true,则返回为指定发布者类和它的所有父类
* 注册的监听器提供者;如为flase,则只返回为指定发布者类注册的监听
* 器提供者
* @return 相应的监听器提供者的集合(永不为null)
*/
private synchronized Collection getListenerSuppliersCopy(Class
publisherClass, boolean checkInheritance){
if ( checkInheritance ) {
Collection publishers = myListenerSuppliersMap.keySet();
Iterator i = publishers.iterator();
Collection listenerSuppliers = new ArrayList();
while (i.hasNext()) {
Class nextPublisherClass = (Class)i.next();
if ( nextPublisherClass.isAssignableFrom(publisherClass) ) {
if ( myListenerSuppliersMap.get(nextPublisherClass) != null ) {
listenerSuppliers.addAll((Collection)
myListenerSuppliersMap.get(nextPublisherClass));
}
}
}
return listenerSuppliers;
} else {
Collection listenerSuppliers = (Collection)
myListenerSuppliersMap.get(publisherClass);
if ( listenerSuppliers == null ) {
return Collections.EMPTY_LIST;
} else {
//如果你决定不使用ArrayList,请改用clone支持的其他cast方式
return (ArrayList)((ArrayList)listenerSuppliers).clone();
}
}
}
/**
* 一个确保值非null的简单方法
*/
protected void assertNotNull(String message, Object object){
if ( object == null ) {
throw new IllegalArgumentException(message);
}
}
//保存“发布者类 -> 监听器提供者的集合”对
protected HashMap myListenerSuppliersMap = new HashMap();
private static DefaultListenerRegistry instance = new DefaultListenerRegistry();
}
第二个提供者示例允许使用无状态会话Bean作为监听器。它用会话Bean的一个EJBHome构造,利用create()方法返回一个可用的无状态会话Bean。请注意这个提供者在WebLogic 5.1下运行,这是因为,该服务器串行化对无状态Bean的调用,不会因为同时使用同一无状态Bean而抛出RemoteException异常。
//StatelessSupplier.javapackage com.jwasp.listener;
import java.util.EventListener;
import javax.ejb.CreateException;
import javax.ejb.EJBHome;
import java.rmi.RemoteException;
import java.lang.reflect.Method;
import java.lang.reflect.InvocationTargetException;
/**
* 在getListener方法中,利用指定的监听器(无状态会话Bean)
* 的EJBHome调用create()方法返回一个监听器。请确保EJB容
* 器串行化了对监听器的调用(或者在fireXXX方法中提供对监
* 听器的同步)。
*/
public class StatelessSupplier implements ListenerSupplier {
public StatelessSupplier(EJBHome ejbHome) throws RemoteException{
if ( ejbHome == null ) {
throw new IllegalArgumentException("EJBHome is null");
} else if ( !ejbHome.getEJBMetaData().isStatelessSession() ) {
throw new IllegalArgumentException
("EJBHome should belong to stateless session bean");
}
myEjbHome = ejbHome;
}
public EventListener getListener(Class publisherClass)
throws RemoteException, ListenerActivationException {
try {
Method createMethod = myEjbHome.getClass().getMethod("create", new Class[0]);
Object object = createMethod.invoke(myEjbHome, new Object[0]);
if ( object instanceof EventListener ) {
return (EventListener)object;
} else {
throw new ListenerActivationException("Remote interface doesn't extend EventListener");
}
} catch(NoSuchMethodException nsme) {
throw new ListenerActivationException("Home interface doesn't define create() method");
} catch(SecurityException se) {
throw new ListenerActivationException(se.getMessage());
} catch(IllegalAccessException iae) {
throw new ListenerActivationException(iae.getMessage());
} catch(IllegalArgumentException iare) {
throw new ListenerActivationException(iare.getMessage());
} catch(InvocationTargetException ite) {
throw new ListenerActivationException(ite.getTargetException().getMessage());
}
}
private EJBHome myEjbHome;
}
结束语
本文描述的框架允许你使用分布式的观察者/监听器(不错,监听器也可以是EJB;提供者将负责创建/定位EJB)。但是,它的目标不是替代JMS或消息驱动的Bean,该框架的目标是补充那两种强大的通知机制。结合JMS、消息驱动的Bean,本文描述的框架允许你在面对分布式事件发布者和监听器时,正确地实现Observer模式。
注意发布者不必一定是EJB。当发布者是普通的类时,你同样可以方便地应用本文所描述的框架。
最后,我想要指出,该框架的本质是:在发布者和观察者当时不存在的情况下,建立两者之间的关系。因此,任何想要发布者在创建时配置自己的地方,都可以使用本文所介绍的框架(如果发布者是一个EJB,则配置应该在ejbCreate()/ejbActivate()方法里进行;如果发布者是一个普通的类,则应该在构造函数里进行)。按照这种方法,如果发布者不是一个singleton,你不必担心所有的实例都有一组同样的监听器(或一组同样的实现业务逻辑的功能)。
0
相关文章