OSGi 探秘系列 (4)- OSGi Bundle之依赖关系
在之前一篇我写的文章OSGi 探秘系列 (1)- 概述什么是OSGi框架中,OSGi对Java平台的类加载机制的一个重要改进就是支持包级别的类导入和导出,而不仅仅在jar级别。本文将详细介绍OSGi这一改进机制,并介绍在OSGi中如何定义和解析Bundle之间的依赖关系。
在Java以及很多其它面向对象编程语言中,类之间的依赖关系都是在code中隐含的,当依赖关系不满足的时候,在运行时会产生ClassNotFoundException或者NoClassDefFoundError之类的异常或者错误。OSGi则改变了这一状况,类之间的依赖关系是显式声明的以及版本化的。显式声明指的是依赖关系是按照某种标准的方式写在文件里,任何人任何程序都可以访问和看懂,而不是写在代码里;版本化指的是依赖关系显示声明所依赖的类的版本。 我们先通过一个例子介绍如何在Bundle中Export和Import包。该例子实例了一个Mailbox服务,包括了两个Bundle。 =============================== 第一个Bundle =============================== 包含了两个接口 // org.osgi.message.reader.api.MailBox.java packageorg.osgi.message.reader.api; // org.osgi.message.reader.api.Message.java packageorg.osgi.message.reader.api; importjava.io.InputStream; 创建一个mailbox_api.bnd的文件,文件内容如下 Export-Package: org.osgi.message.reader.api;version=1.0.0 右击然后点击Make Bundle,可以看到生成了Bundle的jar文件mailbox_api.jar. =============================== 第二个Bundle =============================== 该Bundle包含了对上面两个接口的实现类。 //org.osgi.message.reader.fixedmailbox.FixedMailbox.java packageorg.osgi.message.reader.fixedmailbox; // Omit the implementation of the inherited methods from MailBox.java } // org.osgi.message.reader.fixedmailbox.StringMessage.java importjava.io.ByteArrayInputStream; // Omit the implementation of the inherited methods from Message.java
创建一个fixed_mailbox.bnd的文件,文件内容如下 Private-Package: org.osgi.message.reader.fixedmailbox; Bnd-LastModified 1262573897968 在上面的例子中,我们看到第一个Bundle所Export的包org.osgi.message.reader.api被第二个Bundle Import了,我们就说第二个Bundle对第一个Bundle存在依赖关系。 在OSGi R4中,引入了一个新的header叫做"Required-Bundle",其实际效果等于Import该Bundle所有Export出来的包。我觉得这其实是一个非常有用的header。想象一下在一个有数以千计的Bundle的系统中,如果逐个指定包层次的依赖关系将会是怎样一个噩梦。另外值得注意的是,所有java.*的包都是默认被Import的,不需要再在MANIFEST文件中声明,但是javax.*的包则需要声明。 从上面我们可以看到OSGi如何通过显示声明的方式定义Bundle之间的依赖关系,下面我们介绍在依赖声明中如何指定版本化信息。在OSGi中,版本信息的格式是三个数字段加上一个字符串段,比如"1.2.3","1.1","1.0.2.beta1". 下面这个例子可以让大家了解如何基本使用版本信息。 Export-Package org.osgi.message.reader.api;version="1.0.0" Bundle-Version 1.0.0 另外,版本也可以用范围的形式指定。假设版本值用变量v表示,(1.0,2.0)表明1.0<v<2.0,[1.1.2,1.2.1]表明1.1.2<= v<=1.2.1,以此类推。下面两个例子示范了如何在Import包以及Bundle中使用版本范围。 Import-Packageorg.apache.log4j.*; version = " [ 1 . 2,1 . 3 ) " Require-Bundlemailbox-api;bundle-version="[1.0.0,1,1.2]"
在这篇文章的最后,我再总结一下OSGi框架下的类加载机制。当Bundle被安装后,OSGi按照以下顺序进行类加载: 1) 从上层类加载器中加载java.*的包 2) 加载MANIFEST中的Import-Package所指定的包 3) 加载MANIFEST中的Require-Bundle所指定的Bundle 4) 加载该Bundle自身包含的类 5) 从Fragment bundle中加载类。 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |