OSGi 框架事件

来源:互联网 发布:简明python教程在哪买 编辑:程序博客网 时间:2024/05/01 02:02

OSGi 框架支持以下生命周期层事件:

l         BundleEvent 报告bundle的生命周期改变

l         FrameworkEvent 报告框架的启动、启动级别的改变、包的更新或者是捕获的错误。

事件的实际类型可以通过getType方法获得。返回的是一个整形数据,在类中定义了整形数据的含义。因此,可以在以后对事件进行扩充。忽略处理不可识别的事件。

1.   监听器

每一种类型的事件对应有一个监听器接口。下面描述了这些监听器:

l         BundleListenerSynchronousBundleListener bundle的生命周期信息改变后使用一个BundleEvent类型的事件来调用。

SynchronousBundleListener的调用是同步的,在处理这个事件的时候,必须要先于调用其他任何BundleListener对象。下面描述了当框架进入到另一个状态时,发出的一系列的事件:

l         INSTALLED – 框架安装后发出。

l         RESOLVED– 框架解析一个bundle后发出。

l         STARTING – 当框架即将启动一个bunlde时发出。只发送到SynchronousBundleListener对象。

l         STARTED – 当框架已经启动了一个bundle后发出。

l         STOPPING – 当框架即将停止一个bundle时发出。只发送到SynchronousBundleListener 对象。

l         STOPPED– 当框架停止了一个bundle时发出。

l         UNINSTALLED – 当框架卸载了一个bundle后发出。

l         UNRESOLVED – 当框架检测到一个bundle变成不可解析的时候发出;当刷新或者更新一个bundle的时候发生这样的事件。当使用包管理API来更新一系列的bundle时,那么序列中的每一个bundle都有抛出一个UNRESOLVED BundleEvent事件。这个事件必须要等到序列中所有的bundle都已经停止,并且序列中没有任何bundle重新启动才抛出,这是由于使用同步bunle监听器。RESOLVED UNRESOLVED并不需要成对出现。

l         UPDATED – bundle更新之后发出。

l         FrameworkListener 发生FrameworkEvent类型的事件后调用。

框架事件有以下类型:

l         ERROR – 需要操作者立即处理的重要错误。

l         INFO – 在特殊情况下需要的一般的信息。

l         PACKAGES_REFRESHED – 框架更新了包。

l         STARTED – 框架已经完成了初始化,正在普通模式下运行。

l         STARTLEVEL_CHANGED – 在设置和处理一个新的启动级别后由框架发出。

l         WARNING – 警告,提示操作者不是至关重要的但是存在潜在错误的信息。

在接口BundleContext中定义了可用于添加和移出每一种类型的监听器的方法。

除非一些特殊情况,事件是可以进行异步处理的,也就说并不是必须要使用和产生事件的同一个线程中来处理事件。并没有定义事件监听器的线程。

如果对于监听器的回调产生了不可检查的异常,那么在框架中必须要抛出一个框架事件FrameworkEvent.ERROR。除非回调发生在传递事件FrameworkEvent.ERROR过程中(为了防止死循环)。

2.    事件发送

如果框架是异步传递事件的,那么框架必须:

l         在事件传递之前,保存一个事件发生时的监听器列表的快照(而不是在以后进行是在事件发送之前)。这样监听器就在事件发生之后不需要访问列表。

l         确保在保存快照的时候监听器所属的bundle处于活动状态。

如果框架在事件发生时没有捕获到当前的监听器列表,而是等到事件传递之前进行,那么可能导致以下错误:一个bundle已经启动并注册了一个事件监听器,bundle就可以通过自己的BundleEvent.INSTALLED来查看自己的事件。

下面三种情景说明了上述的情况:

1.       情景一事件顺序:

l         发生事件A

l         注册监听器1

l         尝试异步传递事件A

异常状态:监听器1不能接收到事件A,由于它不是在事件发生前注册的。

2.       情景二事件顺序:

l         注册监听器2

l         发生事件B

l         取消注册监听器2

l         尝试异步传递事件B

异常状态:监听器2不能接收到事件B,由于监听器2时在事件B发生时注册的。

3.       情景三事件顺序:

l         注册监听器3

l         发生事件C

l         停止注册监听器3bundle

l         尝试异步传递事件C

异常状态:监听器3肯定不能接收到事件C,这是由于它的BundleContext对象不存在。

3.    同步处理缺陷

通常,调用监听器的bundle不应该保留有任何Java监控器。这也就是说在初始化回调时,框架和同步事件的发送者都应该不是处于监控器之中。

Java监控器的目的在于保护更新数据的结构。也就是一小段不能调用任何不可监视代码的代码。在同步代码中调用OSGi框架可能导致不可预测的结果。其中之一有可能是导致死锁。死锁是指两个线程由于相互等待而阻塞。

可以通过超时来解决死锁问题,但是java监控器并没有使用超时。因此,线程一直挂起直到系统重新设置(Java中不赞成所有能停止一个线程的方法)。这种死锁的预防方法就是在同步代码中不调用框架(否则其他代码可能导致回调)。

如果再调用其他代码时,必须要使用锁,那么使用Java监控器来创建一个信号量,这个信号量可以超时,以此来预防死锁。