New-->Plug-in Project
如果你的bundle在启动和关闭的时候需要被通知,可以勾上Options中的第一个,实现BundleActivator接口,Finish后我们的第一个Bundle就建好了
Bundle中最重要的一个文件就是bundle的描述文件MANIFEST.MF,看下该文件中的内容Bundle-ManifestVersion
该属性头告诉OSGi容器,本Bundle将遵循OSGi规范,数值2表示本Bundle和OSGi规范第4版本兼容;如果该属性的数值为1,那么则表示本包和OSGi版本3或更早版本兼容。
Bundle-Name
该属性头为本Bundle定义了一个简短的、可以阅读的名称;
Bundle-SymbolicName
这个属性头为本Bundle定义了一个唯一的、非本地化的名字;当您需要从别的Bundles中访问某一指定的Bundle时,您就要使用这个 名字。
Bundle-Version
该属性头给出了本Bundle的版本号。
Bundle-Activator
该属性头给出了本Bundle中使用的监听器类名字,这个属性值是可选的。监听器将对Activator中的start()和stop()方法 监听。
Bundle-Vendor
该属性头是对本Bundle发行商的表述。
Bundle-RequiredExecutionEnvironment
Bundle运行所依赖的环境
Import-Package
定义bundle的导入包。
Dependencies中添加bundle所依赖的bundle或所依赖的包
Runtime中设置该bundle导出的包
Bundle导出后其实就是一个jar文件,这个jar文件和普通的jar文件唯一不同的地方就是Meta-inf目录下的MANIFEST.MF文件的内容,关于Bundle的所有信息都在MANIFEST.MF中进行描述,在OSGI框架中对于每个Bundle采用的是独立的classloader机制,这也就意味着不能采用传统的如引用其他Bundle的工程来实现Bundle间的协作了,那么在OSGI框架中Bundle之间是怎么协作的呢,在OSGI框架中对于每个Bundle可以定义输出的包以及引用的包,这样在Bundle间就可以共享包中的类了,尽管这样也可以直接实现简单的Bundle的协作,但在OSGI框架中更加推荐的是采用Service的方式,每个Bundle可以通过BundleContext注册对外提供的服务,同时也可以通过BundleContext来获得需要引用的服务,采用Service-Oriented的方式可以使得对外提供的服务能够更加的封闭,不需要为了使用别的Bundle提供的Service而做环境依赖等的设置,同时,Bundle还可以采用Require-Bundle的方式来直接引用其他的Bundle,不过不推荐使用这种方式,耦合度太高。运行新建的bundle
把需要的bundle勾上,Run
bundle在其生命周期的6种状态和OSGi控制命令台的一些常用命令
INSTALLED
Bundle已经成功的安装了。
RESOLVED
Bundle中所需要的类都已经可用了,RESOLVED状态表明Bundle已经准备好了用于启动或者说Bundle已被停止。
STARTING
Bundle正在启动中,BundleActivator的start方法已经被调用,不过还没返回。
ACTIVE
Bundle已启动,并在运行中。
STOPPING
Bundle正在停止中,BundleActivator的stop方法已经被调用,不过还没返回。
UNINSTALLED
Bundle已经被卸载了。
安装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。
Osgi命令控制台常用命令
ss:该命令显示所有已安装的Bundles及它们的状态,它将显示BundleID,Bundle状态,Bundle的简短名;
start【bundleid】:启动对应id的Bundle
stop【bundleid】:停止对应id的Bundle
update【bundleid】:更新对应id的Bundle
install【bundleid】:安装对应id的Bundle
uninstall【bundleid】:卸载对应id的Bundle
exit: 退出osgi环境
refresh【bundleid】: 刷新对应id的Bundle
ls:显示所有services 如果没有发布service会显示找不到该命令
ls –c 【bundleid】:显示该bundle中所有发布service的详细信息,对与unsatisfied的component查错很有用