基于 EventAdmin 服务的 Bundle间通讯

OSGi 的 Event Admin 服务规范提供了开发者基于发布 / 订阅模型,通过事件机制实现 Bundle 间协作的标准通讯方式。

事件发布者使用 Event Admin 服务发送基于主题 (Topic) 的事件,任何对某一主题感兴趣的事件订阅者都会收到该事件,并且做出相应的反应。

如何发布事件

我们遵循以下的步骤,通过 Event Admin 发布事件:

获得实现了 org.osgi.service.event.EventAdmin 接口的 Event Admin 服务引用。
拟定事件的主题。
指定事件所携带的 key/value 属性集。
使用 Event Admin 提供的 postEvent 或者 sendEvent 方法发布事件,postEvent 使用同步的方式发布事件,即:等到所有的事件订阅者响应了该事件,方法调用返回,而 sendEvent 使用异步的方式发布事件。
发布事件:

/**
* 自定义Bundle(服务)实现类,并且将事件发送到EventAdmin中
* @author zxpWork
*
*/
public class HelloWordImpl implements HelloWord {

public String getHello() {
BundleContext context=Activator.contet;
ServiceReference ref =context.getServiceReference(EventAdmin.class.getName()); //获取EventAdmin服务
if(null!=ref){
EventAdmin eventAdmin = (EventAdmin)context.getService(context.getServiceReference(EventAdmin.class.getName()));
if(eventAdmin!=null) {
System.out.println("event started");
// eventAdmin.postEvent(new MyEvent()); //异步 :发送事件,不管监听方是否接收成功直接返回。
eventAdmin.sendEvent(new MyEvent());//同步 :发送事件,需要所有监听方正常接收成功后才有返回。
System.out.println("event returned");
}
}
return "Hello OSGi Server!";
}


/**
* 自定义事件,继承Event
* @author zxpWork
*
*/
public class MyEvent extends Event {

public static final String MY_TOPIC="org/zxp/event1/event/MyEvent";

public MyEvent(String arg0, Dictionary arg1) {
super(arg0, arg1);
}

public MyEvent(){
super(MY_TOPIC, null);
}

public String toString(){
return "MyEvent";
}

}
}


public class Activator implements BundleActivator {

public static BundleContext contet;

private ServiceRegistration sr;

/*
* (non-Javadoc)
* @see org.osgi.framework.BundleActivator#start(org.osgi.framework.BundleContext)
*/
public void start(BundleContext context) throws Exception {
System.out.println("EventService start!");
contet=context;
sr=context.registerService(HelloWord.class.getName(), new HelloWordImpl(), null);
/*注册ServiceTracker*/
// ServiceTracker st=new ServiceTracker(context,EventAdmin.class.getName(),null);
// st.open();
}

/*
* (non-Javadoc)
* @see org.osgi.framework.BundleActivator#stop(org.osgi.framework.BundleContext)
*/
public void stop(BundleContext context) throws Exception {
System.out.println("EventService stop!");
sr.unregister();
}

}

如何订阅事件

遵循以下的步骤,来订阅被 Event Admin 发布的事件:

确定你想要订阅那些主题事件,支持通配符。
如果需要,根据事件的属性确定事件的过滤原则。
发布实现了 org.osgi.service.event.EventHandler 接口的你的事件订阅服务,以便当你感兴趣的事件发生后,Event Admin 能通知到你。
事件订阅:

/**
* 自定义事件处理(监听)类
* @author zxpWork
*
*/
public class MyEventHandler implements EventHandler {

public void handleEvent(Event event) {
System.out.println("MyEventHandle started:"+event);
try {
Thread.currentThread().sleep(5*1000);
} catch (InterruptedException e) {

}
System.out.println("MyEventHandle ok--"+event);
}

}


public class Activator implements BundleActivator {

/*
* (non-Javadoc)
*
* @see
* org.osgi.framework.BundleActivator#start(org.osgi.framework.BundleContext
* )
*/
public void start(BundleContext context) throws Exception {
System.out.println("EventHandler start!");
/*
* 添加事件处理器 (监听).
*/
String[] topics = new String[] { MyEvent.MY_TOPIC };
Hashtable<String, String[]> ht = new Hashtable<String, String[]>();
ht.put(EventConstants.EVENT_TOPIC, topics);
EventHandler myHandler = new MyEventHandler();//新建事件处理器(监听)
context.registerService(EventHandler.class.getName(), myHandler, ht);//注册事件处理器(监听)
System.out.println("event handler registered");

/*
* 获取自定义Bundle服务
*/
HelloWord hello1 = (HelloWord) context.getService(context
.getServiceReference(HelloWord.class.getName()));
System.out.println(hello1.getHello());
}

/*
* (non-Javadoc)
*
* @see
* org.osgi.framework.BundleActivator#stop(org.osgi.framework.BundleContext)
*/
public void stop(BundleContext context) throws Exception {
System.out.println("EventHandler stop!");
}

运行结果:

osgi> EventHandler start!
event handler registered
EventService start!
event started
MyEventHandle started:MyEvent
MyEventHandle ok--MyEvent
event returned
Hello OSGi Server!

从这个例子中可以看到,发布事件的 Bundle 与订阅事件的 Bundle 之间没有任何的相互依赖关系,它们之间以 Event Admin 服务为中间人 (Broker),以事件 (Event) 为消息载体,进行 Bundle 间的松散协作。

基于 Event Admin 服务的 Bundle 通讯,我们总结如下几点:

OSGi Event Admin 的事件模型,与传统的 JMS 相比,OSGi Event Admin 事件不是持久化的,也就是说,通过 Event Admin 发布的事件只在本次应用会话期间存在,当 OSGi 应用重新启动后,所有的未处理的事件将全部丢失。
由于 OSGi 服务的动态特性,使用该模型时,必须考虑到以下的情况:由于订阅事件的 Bundle 可以在任意运行时刻注册实现了 org.osgi.service.event.EventHandler 接口的事件订阅服务,所以开发者不能期望订阅者总能够收到在本次会话期间事件发布者发布的所有事件,一个典型的情况是,如果在发布者发布事件的时候,订阅 者服务尚未注册,其结果是,该订阅者错过这次事件。
在 Equinox 环境下,如果想使用 Event Admin 服务,需要额外从http://www.eclipse.org/equinox/bundles/ 下载,具体的 Event Admin 服务 Equinox 实现 org.eclipse.equinox.event Bundle, 在默认的情况下,org.eclipse.equinox.event Bundle 并没有包含在 Equinox 的 SDK 里。

小结:
OSGi 服务层所提供的服务模型,其动态发现、动态绑定、契约与实现相分离等特性,可以帮助开发者实现组件之间依赖保持在接口之间,而与具体实现代码相对松散的应 用逻辑。在此基础上 OSGi 提供了基于事件的 Event Admin 服务。Event Admin 服务本质上是基于消息的发布 / 订阅机制,对于 OSGi 的开发者来说,Event Admin 服务可以帮助他们实现组件间更为松散的,不依赖任何接口定义的协作逻辑。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值