OSGi的EventAdmin
来源:互联网 发布:合金装备5连接网络 编辑:程序博客网 时间:2024/06/04 17:47
大家都知道Eventing或者Publish / Subscribe机制对于低耦合系统的重要性。很多时候写一个listener接口,一个list用来记录所有的listener,当有event发生的时候,就遍历list来通知每个listener,这种方法最简单明了,但在模块化开发(比如OSGi)中,如果在模块之间实现Publish Subscribe 模式就没有这么简单了。就好像logging这么简单的东西,到了模块化开发中也颇费周折一样。原因很简单,想要从模块化中获利(“利”指的是热启动,热关闭,模块之间耦合度降低,灵活性大大加强,可扩展性加强,健壮性加强,少了几个模块,其他不强制依赖这几个模块的其他模块照样运行),就必然在一些"简单"功能的实现上要多费思量。
好在OSGi准备了EventAdmin service,来解决这个模块间eventing的问题。如果你熟悉JMS中的messaging机制,或者GWT的EventBus的话,EventAdmin基本上是同一回事。你所需要的就是org.eclipse.osgi.services这个插件。
下面这个例子是基于Eclipse这个IDE(Eclipse本身是基于OSGi的,所以对于任何基于OSGi的项目,笔者认为Eclipse是不二选择)
首先新建一个Plugin Project,在MANIFEST.MF中加两个依赖
新建一个类,先称之为EventBus,它将注册OSGi的Declarative Service,获取一个EventAdmin的实例
import org.osgi.service.event.EventAdmin;/** * <ul> * <li>Title: EventBus</li> * <li>Description: This class instantiates the <code>Event Admin</code> service. Bundles wishing to publish events must obtain the Event Admin service and call one of the event delivery methods.</li> * <li>Created: Oct 15, 2012 by: JQin</li> * </ul> */public class EventBus { /** * The eventBus. */ private static EventAdmin eventBus; /** * @return */ public static EventAdmin getEventBus() { return eventBus; } /** * Method will be used by DS to set the <code>org.osgi.service.event.EventAdmin</code> service. * @param eventBus */ public synchronized void setEventBus(EventAdmin eventBus) { EventBus.eventBus = eventBus; System.out.println("EventAdmin service is set!"); //$NON-NLS-1$ } /** * Method will be used by DS to unset the <code>org.osgi.service.event.EventAdmin</code> service. * @param eventBus */ public synchronized void unsetEventBus(EventAdmin eventBus) { if (EventBus.eventBus == eventBus) { EventBus.eventBus = null; } System.out.println("EventAdmin service is unset!"); //$NON-NLS-1$ }}
在OSGi中注册Declarative Service的步骤很简洁:在Project根目录下新建一个文件夹OSGI-INF,然后在这个文件夹中新建一个Component Definition文件
<?xml version="1.0" encoding="UTF-8"?><scr:component xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0" name="com.jqin.common.eventbus"> <implementation class="com.jqin.common.eventbus.EventBus"/> <reference bind="setEventBus" cardinality="1..1" interface="org.osgi.service.event.EventAdmin" name="EventAdmin" policy="static" unbind="unsetEventBus"/></scr:component>
在Eclipse里面运行的时候,记得要保证这么几个插件的存在:
org.eclipse.equinox.ds
org.eclipse.equinox.event
并且要设置为自动开始(auto-start 为 true)
当点击Run之后,如果Console立刻打印了
EventAdmin service is set!
就表示这个EventAdmin Declarative Service设置成功了!
使用起来非常方便,首先在这个插件的MANIFEST.MF中开放EventBus所在的包给其他插件。
和REST中定位资源的方式类似,EventAdmin通过定义成为topic的URI来区分不同的Event,比如下面这个event的topic就是
org/eclipse/equinox/events/MemoryEvent/CRITICAL
任何subscribe了这个topic的listener都可以接收到event信息
Event event =newEvent("org/eclipse/equinox/events/MemoryEvent/CRITICAL", null);eventAdmin.postEvent(event);
EventAdmin发送Event的方法有两种,一种是同步发送,即sendEvent,另一个是异步发送,即postEvent。二者的区别是sendEvent会block caller,确保所有的subscriber都接收到了event,而postEvent则是把event排到EventAdmin的一个queue里面,然后caller就不管了,也不会被block。
在新建Event的时候,除了需要topic来定义这个Event的URI以外,Event还支持一个Map变量用来存储属性,这个属性Map通常就被用来保存需要在Event中传输的数据。
下面介绍一个如何注册成为某个或者某些event的subscriber,同样通过Declarative Service。
先新建一个subscriber类
import org.osgi.service.event.Event;import org.osgi.service.event.EventHandler;public class Subscriber implements EventHandler { /* * (non-Javadoc) * @see org.osgi.service.event.EventHandler#handleEvent(org.osgi.service.event.Event) */ @Override public void handleEvent(Event event) { // TODO Auto-generated method stub }}
在OSGI-INF中新建一个Component Definition文件,注册一个Provided Service
同样在这个文件中,注册一个名为event.topics的属性
完成后的component.xml文件类似于这样
<?xml version="1.0" encoding="UTF-8"?><scr:component xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0" name="subscriber"> <implementation class="Subscriber"/> <property name="event.topics" type="String" value="org/eclipse/equinox/events/MemoryEvent/*"/> <service> <provide interface="org.osgi.service.event.EventHandler"/> </service></scr:component>
这就表示这个Subscriber注册了org/eclipse/equinox/events/MemoryEvent/* 这个topic,大家都知道 * 标记指的是任何,所以前面发送的Event topic是org/eclipse/equinox/events/MemoryEvent/CRITICAL自然也其中。
推荐基于OSGi模块化开发的程序员使用EventAdmin的原因和推荐使用Publish Subscribe pattern,以及eventing/messaging机制的原因一样,减少模块间的依赖。使用模块化开发的最重要原因就是低耦合,所以这一点很重要。
- OSGi的EventAdmin
- osgi之Eventadmin通信
- 基于 EventAdmin 服务的 Bundle间通讯
- 对OSGI的个人理解,OSGI是什么,OSGI做什么
- [OSGi] 启动OSGi的Declarative Services
- OSGi介绍及OSGi的Bundle应用
- [OSGi] 启动OSGi的Declarative Services
- OSGi介绍(六)OSGi的service
- OSGi介绍及OSGi的Bundle应用
- 【OSGi】OSGi框架的三个层次
- 【OSGi】OSGi框架的三个层次
- OSGi规范的实现
- OSGI的特点
- OSGi: Eclipse的根基
- OSGI+Spring的优势
- 使用OSGI的服务
- OSGi的编程思想
- 关于OSGI的概念
- 将自定义对象作为元素存到ArrayList集合中,并去除重复元素
- 对象数组或list排序及Collections排序原理
- java中的Iterator和Iterable 区别 ,以及为么要有iterable接口
- 浅谈大型网站的算法和架构(1)
- 关于函数strtok和strtok_r的使用要点和实现原理
- OSGi的EventAdmin
- UNIX文件结构(转自UNIX/AIX操作系统基础教程)
- http中的gzip
- UVa 10125 - Sumsets
- 【OI杂记】求二叉树上任意两点的最短路径上的边权最大值
- Fedora 17 下运行Kettle遇到"A fatal error has been detected by the Java Runtime Environment"
- platform_device与platform_driver
- 链栈
- eclipse 使用点滴