针对事件的实现,OSGi中的 Event Admin 服务规范提供了基于发布 / 订阅模型(publish-subscribe model)这种方法,Event Admin 服务将事件从发布者(Publishers)转发到订阅者(Subscribers),从而实现bundle间的通信。具体流程如下图所示:
事件由
org.osgi.service.event.Event对象来表示,事件有两个要素:主题(Topic)和属性(Properties)。通过主题匹配,事件处理函数只需响应自己感兴趣的事件。
事件的发布有同步(postEvent())和异步(sendEvent())两种方式:前者要等到所有的事件订阅者都响应了该事件才返回, 而后者则是信息发布后直接返回。
下面直接以例子来说明
工程截图如下:
详细代码如下:
事件发布:
/*
* Created on Sat Aug 04 10:32:34 CST 2012
*/
package osgi.event.publisher;
import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;
/*
* Created on Wed Aug 01 15:46:40 CST 2012
*/
import java.util.HashMap;
import java.util.Hashtable;
import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceReference;
import org.osgi.service.event.Event;
import org.osgi.service.event.EventAdmin;
import org.osgi.service.event.EventConstants;
public class Activator implements BundleActivator {
boolean flag = true;
public static BundleContext cont;
private ServiceReference sr;
EventAdmin ea = null;
HashMap properties = null;
Event event = null;
/* (non-Javadoc)
* @see org.osgi.framework.BundleActivator#start(org.osgi.framework.BundleContext)
*/
public void start(BundleContext context) throws Exception {
sr = context.getServiceReference(EventAdmin.class.getName());
if (sr == null) {
throw new Exception("Failed to obtain EventAdmin service reference!");
}
ea = (EventAdmin) context.getService(sr);
if (ea == null) {
throw new Exception("Failed to obtain EventAdmin service object!");
}
while(flag){
if(ea != null){
properties = new HashMap();
properties.put(EventConstants.BUNDLE_SYMBOLICNAME, "test.first");
// Creating events with topic
event = new Event("my_osgi_test_event", properties);
ea.postEvent(event); //asynchronous
System.out.println("send event!");
try {
Thread.sleep(5000);
} catch(InterruptedException ie) {}
}
}
}
/* (non-Javadoc)
* @see org.osgi.framework.BundleActivator#stop(org.osgi.framework.BundleContext)
*/
public void stop(BundleContext context) throws Exception {
flag = false;
}
}
事件订阅:
1:首先实现事件处理:
package osgi.event.subsriber;
import org.osgi.service.event.Event;
import org.osgi.service.event.EventHandler;
public class MyEventHandler implements EventHandler {
public void handleEvent(Event event) {
System.out.println("test event received--");
System.out.println("handle event start--"+event);
try {
Thread.currentThread().sleep(2000);
} catch (InterruptedException ex) {
}
}
}
2:事件订阅:
/*
* Created on Wed Aug 01 15:48:27 CST 2012
*/
package osgi.event.subsriber;
import java.util.Dictionary;
import java.util.HashMap;
import java.util.Hashtable;
import org.osgi.framework.BundleActivator;
import org.osgi.framework.ServiceRegistration;
import org.osgi.framework.BundleContext;
import org.osgi.service.event.Event;
import org.osgi.service.event.EventHandler;
import org.osgi.service.event.EventAdmin;
import org.osgi.service.event.EventConstants;
import org.osgi.framework.ServiceReference;
public class Activator implements BundleActivator {
public static BundleContext cont;
private ServiceReference sr;
EventAdmin ea = null;
HashMap properties = null;
Event event = null;
/*
* event topic
*/
final static String[] topic = { "my_osgi_test_event" };
ServiceRegistration register = null;
/* (non-Javadoc)
* @see org.osgi.framework.BundleActivator#start(org.osgi.framework.BundleContext)
*/
public void start(BundleContext context) throws Exception {
Dictionary dict = new Hashtable();
dict.put(EventConstants.EVENT_TOPIC, topic);
EventHandler myHandler = new MyEventHandler();
// Registering the EventHandler
register = context.registerService(EventHandler.class.getName(), myHandler, dict);
if (register != null) {
System.out.println("event handler registered!");
}
}
/* (non-Javadoc)
* @see org.osgi.framework.BundleActivator#stop(org.osgi.framework.BundleContext)
*/
public void stop(BundleContext context) throws Exception {
register.unregister();
System.out.println("event handler unregistered!");
}
}
运行结果如下:
[stdout] send event!
[stdout] test event received--
[stdout] handle event start--org.osgi.service.event.Event [topic=my_osgi_test_event]
[stdout] send event!
[stdout] test event received--
[stdout] handle event start--org.osgi.service.event.Event [topic=my_osgi_test_event]
[stdout] send event!
[stdout] test event received--
[stdout] handle event start--org.osgi.service.event.Event [topic=my_osgi_test_event
注:本次演示的OSGi是基于knopflerfish平台, 缺省状态下并没有包含事件相关的包,需要要额外下载并添加至工程中(本次版本为event_all-3.0.6.jar)。