2.2 Bundle
从本节开始,一直到本书结束,我们都会不断地提起“Bundle”这个词。Bundle是OSGi中最基本的单位,通俗地讲,如果说OSGi是基于Java平台的“模块化开发体系”,那么Bundle便是其中的“模块”。
OSGi中的Bundle是在JAR文件格式规范基础上扩展而来的,一个符合OSGi规范的Bundle首先必须是一个符合JAR文件格式规范的JAR包。与JAR文件格式兼容这点虽然没有太多技术含量可言,但是这个简单的举措极大地加速了OSGi的发展传播,它令OSGi的Bundle可以不经任何修改就直接应用于非OSGi的系统之中,也为将非OSGi的JAR包转换为可在OSGi系统运行的Bundle提供了很大的便利。
Bundle相对普通的JAR文件主要进行了以下三个方面扩展。
JAR文件格式规范里定义的/META-INF/MANIFEST.MF文件用于描述JAR包的元数据信息,如JAR包的版本、数字签名信息等,Bundle在MANIFEST.MF文件中添加了大量扩展定义,如描述该Bundle可以提供哪些资源、依赖哪些其他Bundle、启动或卸载时要执行哪些动作等,这部分内容我们会在2.3节中详细介绍。
加入了一个可选的/OSGI-OPT文件夹,可以在其中保存一些与Bundle运行无关的信息,比如Bundle源码、软件说明书等。Bundle的使用者可以从中获取一些额外的信息,也可以安全地删除该文件夹,以节约OSGi系统的存储空间。
Bundle中可以包含一些具备特殊含义的程序和资源,如使用Bundle-Activator定义的初始化类、定义在OSGI-INF/l10n目录中的本地化信息等。
Fragment Bundle是一种特殊的Bundle,它无法独立存在,必须依附于某个其他的普通Bundle来使用,可以将它视为“Bundle的插件”、“模块中的模块”。
Fragment Bundle经常用来提供某些可选的功能,譬如为某个实现具体功能的Bundle提供一个中文语言包。有这个语言包,实现功能的Bundle能显示中文界面;在没有这个中文语言包时,实现功能的Bundle也能够正常使用。Fragment Bundle的另一项主要用途是隔离Bundle中经常变动的部分,譬如把系统的内部配置文件(开发模式还是生产模式、连接的数据库地址、调试级别等)集中在Fragment Bundle中,通过更换不同的Fragment Bundle来实现配置快速切换。
从静态角度(开发期)来看,Fragment Bundle与普通Bundle没有太大区别,它们都以JAR文件格式为基础,具备相同的元数据信息标记,标记的含义与设置方式也一样。区别仅仅是Fragment Bundle的元数据中会使用Fragment-Host标记说明它的宿主Bundle。
从动态角度(运行期)来看,Fragment Bundle与普通Bundle在运行时的处理差别却非常大,最重要的一点差异是Fragment Bundle不具备自己独立的类加载器。OSGi利用每个Bundle独立的类加载器互相协作来维护Bundle间导入、导出的依赖关系。没有类加载器,就无法直接与其他Bundle交互,必须依附于宿主,使用宿主Bundle的类加载器完成。关于这部分内容,我们在后面会有更详尽的介绍。