注: 摘自BlueDavy的OSGi实战www.riawork.org
OSGI框架可以动态的对Bundle的生命周期进行管理。
Bundle的状态分为六种:
-
INSTALLED - Bundle已经成功的安装了。
-
RESOLVED - Bundle中所需要的类都已经可用了,RESOLVED状态表明Bundle已经准备好了用于启动或者说Bundle已经被停止。
-
STARTING - Bundle正在启动中,BundleActivator的start方法已经被调用,不过还没返回。
-
ACTIVE - Bundle已启动,并在运行
-
STOPPING - Bundle正在停止中,BundleActivator的stop方法已经被调用,不过还没返回。
-
UNINSTALLED - Bundle已经被卸载了。
来看看基于Lifecycle Layer是怎么完成这些状态的转变的:
安装Bundle
通过BundleContext的installBundle方法来安装Bundle,在安装前首先需要对Bundle进行校验,导致Bundle安装失败的原因在之前Module Layer章节中已经描述过了,如校验通过,OSGI框架中将安装Bundle到系统中,此时OSGI框架会分配一个高于现在系统中所有的Bundle的ID给新的Bundle,安装完毕后Bundle的状态就变为INSTALLED了,同时会返回bundle对象,在Bundle安装后就要使用bundle对象来管理Bundle的生命周期状态了。
解析Bundle
Bundle安装完毕后,OSGI框架将对Bundle进行解析,以检测Bundle中的类依赖等是否正确,如有错误则仍然处于INSTALLED状态,如成功Bundle的状态则转变为RESOLVED。
启动Bundle
在启动Bundle前需检测Bundle的状态,如Bundle状态不为RESOLVED,那么需要先解析Bundle,如启动一个解析失败的Bundle,则会抛出BundleException,但此时Bundle的状态仍然会被设置为ACTIVE;如Bundle的状态已经是ACTIVE,那么启动Bundle对它不会产生任何影响。通过BundleContext的getBundle方法可获取指定Bundle ID的Bundle对象,在获取到Bundle对象后可使用Bundle对象的start方法来启动Bundle,此时会调用MANIFEST.MF中的Bundle-Activator属性对应的BundleActivator类的start方法(如存在BundleActivator类),在start方法执行的过程中Bundle的状态为STARTING,当start方法执行完毕后Bundle的状态转变为ACTIVE,如start方法执行失败,Bundle的状态转变为RESOLVED。 BundleActivator类是可以不需要的,建议不要在BundleActivator中初始化过多的东西,这样会使得系统的启动速度会变得很慢,同时也会消耗大量的内存,而且OSGI对于动态性的良好支持使得尽可以在需要的时候才去获取所需的资源。
停止Bundle
通过BundleContext的getBundle方法可获取指定Bundle ID的Bundle对象,在获取到Bundle对象后可使用Bundle对象的stop方法来启动Bundle,此时会调用MANIFEST.MF中的Bundle-Activator属性对应的BundleActivator类的stop方法,在stop方法执行的过程中Bundle的状态为STOPPING,当stop方法执行完毕后Bundle的状态转变为RESOLVED,如stop方法执行失败,Bundle的状态则继续保留原状态。 即使Bundle已经停止,其export的package仍然是可以使用的,这也就意味着可以执行RESOLVED状态的Bundle中export package的类。
卸载Bundle
通过调用Bundle对象的uninstall方法可完成Bundle的卸载,此时Bundle的状态转变为UNINSTALLED。 即使Bundle已卸载,其export的package对于已经在使用的Bundle而言仍然是可用的,但对于新增的Bundle则不可使用已卸载的Bundle export的package。
在管理Bundle的状态时,OSGI主要是通过Bundle、BundleContext这两个对象来实现,Bundle对象中除了对于Bundle的生命周期管理的方法之外,还提供了象getHeaders、loadClass、getResource这些方法,getHeaders方法可用于获取MANIFEST.MF中的属性值,loadClass可用于加载bundle中的类,getResource可用于获取Bundle中的资源文件。
监听Bundle的状态
在监听Bundle的状态上OSGI采用的是典型的Java中的事件机制,在OSGI中事件分为Framework Event和Bundle Event两种,Framework Event用于报告Framework已启动、改变了StartLevel、刷新了packages或是出现了错误;而Bundle Event则用于报告Bundle的生命周期的改变。 可通过实现BundleListener或SynchronousBundleListener来监听Bundle Event,可通过实现FrameworkListener来监听Framework Event。