当前位置: 首页 > news >正文

OSGi Event Admin Service

为什么80%的码农都做不了架构师?>>>   hot3.png

Event Admin是OSGi中用于bundles之间通信的手段,是处理事件的一种通用机制。采用的是pub/sub架构。

发布订阅模型

发布订阅模型应满足的需求:
1. 发布者不应该拥有订阅者的信息。
2. 新的发布者或者新的订阅者的动态增加或者删除不能影响这个发布订阅系统
3. 订阅者不应该阻塞发布者。

在发布订阅模型需要一个中间人来解耦发布者和订阅者。在Event Admin Service中这个中间人就是EventAdmin。

Event Admin service使用Topic来定义分发通道,类似于JMS。发布者发送事件到Topic,订阅者从Topic中接受信息。向Topic发送事件的发布者可以是多个,从Topic接受的订阅者也可以是多个。也就是说是一种多对多的关系。

下面是示例代码:

1
2
3
4
5
6
SimpleSubscriber subscriber = new SimpleSubscriber();
Dictionary dict = new Properties();
dict.put(EventConstants.EVENT_TOPIC,
"manning/osgi/LoginEvent" );
context.registerService(EventHandler. class .getName(),
subscriber, dict);
1
2
3
4
5
6
7
8
9
10
11
public class SimpleSubscriber implements EventHandler {
public void handleEvent(Event event) {
System.out.println( "Received event on topic = " +
event.getTopic());
for (String propertyName :
event.getPropertyNames()) {
System.out.println( "\t" + propertyName + " = " +
event.getProperty(propertyName));
}
}
}

Topic

Topic一般使用类似于java的包名的命名方法,只不过使用右斜杠替换点号。

如果使用”manning/osgi/TravelAgent/*”,则会匹配四层的事件,如
“manning/osgi/TravelAgent/CarEvent”
“manning/osgi/TravelAgent/HotelEvent”
“manning/osgi/TravelAgent/FlightEvent”
但不会匹配
”manning/osgi/TravelAgent/HotelEvent/USA”
“manning/osgi/TravelAgent”
因为它们一个是五层一个是四层。

一个空的或者不存在的EVENT_TOPIC表示不接受任何事件,一个通配符”*”表示接收所有事件。

指定多个订阅者接收多种事件的方法是使用Sring[]。

1
2
3
4
5
6
7
Dictionary dict = new Properties();
dict.put(EventConstants.EVENT_TOPIC,
new String [] { "manning/osgi/TravelAgent/CarEvent" ,
"manning/osgi/TravelAgent/HotelEvent" ,
"manning/osgi/TravelAgent/FlightEvent" });
context.registerService(EventHandler. class .getName(),
subscriber, dict);

Event

Event对象包含Topic名和时间相关的属性信息。自定义事件对象必须继承Event。关于事件的常量最好放到一个Property对象中,而不是写在代码中。

OSGi框架的事件

框架变化:包括启动类路径变化,包刷新,异常,被停止等等。
bundle变化:包括安装,更新,卸载。
服务变化:服务注册,修改,删除。

这些事件可以通过bundle context进行监听。事件会按照注册的顺序进行发送。

1
2
3
4
5
public void start(BundleContext bundleContext) throws Exception {
BundleListener bundleListener = // ...
bundleContext.addBundleListener(bundleListener);
// ...
}
1
2
3
4
5
6
7
public class MyBundleListener implements BundleListener {
public void bundleChanged(BundleEvent bundleEvent) {
if (bundleEvent.getType() == BundleEvent.INSTALLED) {
// ...
}
}
}

BundleEvent 包含一个Bundle类的实例,可以通过这个类来获取bundle的任何内容。

事件处理

EventAdmin的post方法异步发送事件,是非阻塞的;而send则是同步发送事件,是阻塞的。

要注意EvenHandler的handleEvent方法要尽快返回,而且该方法有可能被阻塞。

事件的传递顺序也受发布者发布方式的影响。如果是多线程发送,则无法保证事件的顺序。

如果handleEvent抛出一个异常,该异常并不会传递到发布者,EventAdmin会处理下一个订阅者。

EventAdmin在发送事件时会将所有可用的订阅者做一份拷贝,这就避免了订阅者收到在它存在之前的事件。同时,EventAdmin也会确保订阅者仍然注册并愿意接收事件。

由于发布者和订阅者的解耦,要特别注意发生死锁的情况。

事件过滤

使用EVENT_FILTERE来进行事件过滤。

1
2
3
4
5
Dictionary payload = new Properties();
payload.put( "price" , 80 );
Event event =
new Event( "manning/osgi/TravelAgent/HotelEvent" , payload);
admin.postEvent(event);
1
2
3
4
5
6
Dictionary dict = new Properties();
dict.put(EventConstants.EVENT_TOPIC,
"manning/osgi/TravelAgent/HotelEvent" );
dict.put(EventConstants.EVENT_FILTER, "(price<100)" );
context.registerService(EventHandler. class .getName(),
travelAgentEventHandler, dict);

Event Admin的缺点

1. 事件丢失

如果Event Admin突然挂掉,事件就会丢失。解决的办法是可以通过配置让Event Admin对事件进行持久化存储。

  1. 过滤能力有限

基于LDAP的过滤机制很难实现复杂的事件过滤。解决的方法是通过插入复杂事件处理引擎来实现。
另一个问题是对于大型系统事件的关联属性可能很多,处理起来会非常复杂,而且有可能导致事件内容过大。解决的办法是直接发送
java 对象,然后再接收端进行相应的处理。
另一个缺点是服务保证订阅者接受事件的顺序。解决的方法是扩展EventAdmin。


转载于:https://my.oschina.net/piorcn/blog/313517

相关文章:

  • jQuery ajax - post() 方法
  • 软件培训
  • 如何优化Mysql千万级快速分页
  • MySQL InnoDB体系结构
  • C++ 小复习
  • 在Linux中让echo命令显示带颜色的字
  • ORACLE用户操作的一些常用操作总结【weber出品】
  • QuiltView 瀑布流 (第三方)
  • nginx源码编译
  • varnish代理缓存讲解
  • 泛型排序器 TComparer
  • WinAPI: ShellExecute - 打开外部程序或文件
  • 使用泛型的 TArray 为动态数组排序
  • 序列sequence中的cache问题
  • HBase 专题技术收录
  • “大数据应用场景”之隔壁老王(连载四)
  • CSS3 聊天气泡框以及 inherit、currentColor 关键字
  • Github访问慢解决办法
  • JS实现简单的MVC模式开发小游戏
  • mysql innodb 索引使用指南
  • Nacos系列:Nacos的Java SDK使用
  • Octave 入门
  • React Native移动开发实战-3-实现页面间的数据传递
  • TCP拥塞控制
  • text-decoration与color属性
  • unity如何实现一个固定宽度的orthagraphic相机
  • vue-cli在webpack的配置文件探究
  • 从PHP迁移至Golang - 基础篇
  • 动态规划入门(以爬楼梯为例)
  • 翻译 | 老司机带你秒懂内存管理 - 第一部(共三部)
  • 个人博客开发系列:评论功能之GitHub账号OAuth授权
  • 老板让我十分钟上手nx-admin
  • 前端每日实战 2018 年 7 月份项目汇总(共 29 个项目)
  • 一起参Ember.js讨论、问答社区。
  • - 语言经验 - 《c++的高性能内存管理库tcmalloc和jemalloc》
  • ​软考-高级-系统架构设计师教程(清华第2版)【第12章 信息系统架构设计理论与实践(P420~465)-思维导图】​
  • ​油烟净化器电源安全,保障健康餐饮生活
  • # Apache SeaTunnel 究竟是什么?
  • #stm32驱动外设模块总结w5500模块
  • #使用清华镜像源 安装/更新 指定版本tensorflow
  • #微信小程序:微信小程序常见的配置传值
  • #在线报价接单​再坚持一下 明天是真的周六.出现货 实单来谈
  • $().each和$.each的区别
  • $.ajax()方法详解
  • (007)XHTML文档之标题——h1~h6
  • (day6) 319. 灯泡开关
  • (floyd+补集) poj 3275
  • (附源码)springboot课程在线考试系统 毕业设计 655127
  • (力扣记录)235. 二叉搜索树的最近公共祖先
  • (篇九)MySQL常用内置函数
  • (三)模仿学习-Action数据的模仿
  • (学习日记)2024.01.09
  • (转)Android学习系列(31)--App自动化之使用Ant编译项目多渠道打包
  • *Algs4-1.5.25随机网格的倍率测试-(未读懂题)
  • ../depcomp: line 571: exec: g++: not found