OSGi

来源:互联网 发布:13年总决赛詹姆斯数据 编辑:程序博客网 时间:2024/05/16 23:44
什么是模块化?
模块化是个一般概念,这一概念也适用于软件开发,可以让软件按模块单独开发,各模块通常都用一个标准化的接口来进行通信。实际上,除了规模大小有区别外,面向对象语言中对象之间的关注点分离与模块化的概念基本一致。通常,把系统划分外多个模块有助于将耦合减至最低,让代码维护更加简单。
Java语言并不是按照模块化思想设计的(除了package,按照Java语言规范introduction一 节的介绍,package类似于Modula-3模块),但是在Java社区依然有很多实际存在的模块。任何一个Java类库实际上都是一个模块,无论其 是Log4J、Hibernate还是Tomcat。通常,开源和非开源的应用都会依赖于一个或多个外部类库,而这种依赖关系又有可能传递到其他类库上。

高内聚、低耦合

OSGi(Open Service Gateway initiative)直译为“开放服务网关”,实际上是一个由OSGi联盟(OSGi Alliance)发起的以Java为技术平台的动态模块化规范。

传统 Java 软件问题的根源就是全局的扁平的类加载路径(Classpath),所以 OSGi 采用了一种完全不同的类加载机制,那就是每个模块都有其独立的类加载路径。这几乎解决了传统 Java 在模块化中遇到的所有问题,然而一个新的问题又产生了,软件中的模块是要在一起工作的,这就意味着不同的模块之间存在类共享(不然的话,一个模块如何能够调用到另外一个模块呢),如果每个模块有一个类加载路径,模块间的类共享如何解决?为了解决这个问题,OSGi 定义了一个特殊的并完善的类共享机制。OSGi 将会采用显示的导入和导出机制来控制模块间的类共享。
在 OSGi 中,模块被起了另外一个名字,叫做 bundle。实际上 OSGi 的 bundle 就是一个 Java 的 Jar 文件。OSGi 并没有定义一个新的标准去封装 Java 类和其他的资源文件,标准 Jar 文件可以很好地工作在 Java 应用软件中。在 OSGi 体系里,只是一些新的元数据信息被加入到 Jar 文件中,这些元数据信息使的 Jar 文件变成一个 OSGi 体系中的 bundle。那么什么样的元数据信息被加入进来了呢?
  1. Bundle 的名字。OSGi 提供了一个“symbolic”名字作为这个 bundle 的唯一标识符。 
  2. Bundle 的版本信息。 
  3. Import 和 export 列表。从这个列表,我们可以清楚地知道这个 OSGi bundle 需要导入和导出那些包的类。导入的包是本 bundle 需要用到的外部资源,导出的包是其他 bundle 可以用的本 bundle 中的资源。 
  4. Bundle 需要运行的最小的 Java 版本。这个信息是可选的。 
  5. 种类繁杂的人类可读的其他信息,比如说:本 bundle 的提供者,版权陈述,联系地址等等。
这些元数据信息被放到 Jar 文件的 MANIFEST.MF 文件中,而这个文件是每个标准 Jar 文件的一部分。用一个标准的 Jar 文件作为 OSGi bundle 的一个好处是 bundle 可以被用在 Jar 文件可以出现的任何一个地方,因为 bundle 就是一个纯粹的 Jar 文件。当一个 bundle 用在 OSGi 的运行时之外的时候,这些额外多出来的元数据信息会被 Java 运行时简单地忽略掉,所以说,bundle 是向前兼容的。
为每一个 bundle 提供一个类加载路径意味着什么呢?简单地说我们为每一个 bundle 提供了一个类加载器,这个类加载器能够看到这个 bundle 文件里的类和其他资源文件。但是为了达到多个 bundle 共同工作的目的,在 OSGi 的类加载器之间,类加载请求可以从一个 bundle 的类加载器被委托到另外一个 bundle 的类加载器。回想一下在标准 Java 和 J2EE 中,类加载器是一个树形结构的,类加载请求总是被向上委托给每一个类加载器的父亲。这中类加载机制不允许在水平的树节点之间进行类加载委托。为了让一个类库可以被类加载器树的多个树枝共同所见,我们就需要将这个类库推到这些树枝共同的祖先节点。这样这个版本的类库就会被这些树枝上的所有节点所见,而不管是否这些节点都想看到这个版本的类库。图 1 是一个典型的 J2EE 类加载器层次结构,它展示了为什么类库会不断推高的原因。

图 1. 典型的 J2EE 类加载器层次结构
而树型结构并不是我们需要的,我们真正需要的是网状结构。两个组件之间的依赖关系不是简单的上下级的关系,而应该是一种提供者和使用者的网络关系。类的加载请求被从一个 bundle 的类加载器委托到另外一个 bundle 的类加载器,而这种委托是基于 bundle 之间的这种网状的依赖关系。图 2 给了我们一个 OSGi 中 bundle 之间的网状的依赖关系的例子。

图 2. OSGi 中 bundle 之间的网状的依赖关系
在 OSGi 中,bundle 之间的依赖关系是通过显示的 import 和 export 类包列表来决定的。比如说,在图 2 的 bundle B 中包含一个类包,名字为 com.ibm.bundle.b.somePackage.。Bundle b 就可以选择在它的 MANIFEST.MF 文件去 export 这个类包。而 bundle A 也可以选择去在它的 MANIFEST.MF 文件中 import 类包 com.ibm.bundle.b.somePackage。然后在 OSGi 运行时中,OSGi 框架将负责匹配不同 bundle 的 import 和 export 列表。而这个匹配过程被称为 OSGi 的解决过程(resolution process)。OSGi 的解决过程是相当复杂的,但是这个过程是被 OSGi 框架实现了的,不需要每个 bundle 自己来关心它。每个 bundle 只需要写一些很简单的 import 和 export 声明语句在各自的 MANIFEST.MF 文件里。一旦 OSGi 框架匹配了 bundle A 的 import 列表里的类包 com.ibm.bundle.b.somePackage 与 bundle B 的 export 列表里的类包 com.ibm.bundle.b.somePackage,那么这两个 bundle 就会被连接在一起,而这就意味着当 bundle A 需要载入任何类包 com.ibm.bundle.b.somePackage 里的类时,这个类载入请求就会被委托给 bundle B 的类载入器,而 bundle B 的类载入器将会载入这个类,并将类实例传给 bundle A。而因为 bundle A 依赖 bundle B 和 bundle C, 如果 bundle A import 列表里的所有类包都能在 bundle B 和 bundle C 的 export 列表里发现,那么 bundle A 将会被称为解决成功,它会进入解决了状态(resolved)。如果 bundle A 的 import 列表里需要的某些类包没有在 bundle B 和 bundle C 的 export 列表里发现,那么 bundle A 的解决就没有成功,bundle A 将不能被使用和启动。由此可见,OSGi 中,bundle 之间的依赖关系是通过显示的 import 和 export 列表来决定的。
  1. 隐藏了 bundle 中的信息。 因为在 OSGi 中,bundle 之间的依赖关系是通过显示的 import 和 export 列表来决定的,所以我们没有必要 export 一个 bundle 中的所有的类包,进而能起到隐藏 bundle 中信息的作用。在 OSGi 中,只有那些被显示的 export 出来的类包才能被其他的 bundle import。 
  2. 增加了版本控制并允许多版本并存。 OSGi 不仅仅使 bundle 之间通过类包名相互依赖,它还可以为类包加入版本信息。这是我们能够应付 bundle 的版本变化问题。Export 的类包也可以携带一个版本信息,而 import 却可以引用一个版本范围内的所有类包,这让我们的 bundle 可以依赖一个版本范围内的所有类包。于是说,在 OSGi 中,同一 bundle 的多个版本就可以同时存在。

解释 OSGi 是如果克服版本冲突问题的
OSGi 之所以能够解决 Java 应用软件中组件的版本冲突问题,原因就是 OSGi 的网状类加载器和 OSGi bundle 的版本信息控制。为什么这么说呢? 
  1.  OSGi 的网状类加载器架构使每个 OSGi bundle 都拥有一个独立的类加载器,而 bundle 只是一个标准 Jar 文件。这样,对同一个 bundle 的不同版本,我们就可以创建多个不同的 Jar 文件。这些 Jar 文件的实际内容可以完全一样,而只是文件名不同(甚至文件名都可以相同,因为在 OSGi 框架中,bundle 名和版本的组合才是唯一标识符)。因此这些 Jar 文件,在 OSGi 框架看来,是不同的 bundle,于是同一个组件的不同版本可以被同时载入到 JVM 中,这就解决了 Java 应用软件中同一组件不同版本的并存问题,接下来只要解决版本辨识问题,那么 Java 应用软件中组件的版本冲突问题就会被客服掉了。 
  2. OSGi 添加了版本控制信息来区分同一个 bundle 的不同版本,而且在 OSGi 框架中 bundle 名和 bundle 版本的组合才是这个 bundle 的唯一标识符,于是通过 bundle 的版本控制,同一个 bundle 的不同版本就可以得到区分,而 bundle 直接的依赖关系也可以通过版本来加以限制,从而就能完美的解决 Java 应用软件中组件的版本冲突问题了。

那么 OSGi 是如何进行版本控制的呢?
OSGi 通过在 MANIFEST.MF 文件中添加 Bundle-Version 属性来个为每一个 bundle 添加一个版本信息,而且这个版本信息必须严格遵循:3 数字段 +1 字符段的格式,6.2.0.beta_3 是一个典型有效的 bundle 版本信息。这前面的 3 个数字段就是大家都知道的主版本,小版本和微版本,而那个最后的字母段则是校正段。当前面的 3 个任意一个数字段没有值时,OSGi 将会隐式地将 0 付给这个字段,所以版本 1 是和 1.0、1.0.0 相同的。而如果没给 bundle 指定任意一个版本,那么 0.0.0 将被认为是这个 bundle 的版本信息。
另外 OSGi 中,版本的比较是采用从前到后的比较方式。如果在版本比较时,第一个数字段就不同,那么后面的 3 个字段就不用比较了,因为 OSGi 的前一个版本段是后面所有字段值的总和,所以大版本就不相同的时候,后面的小版本就不需要比较了,比如说:2.0.0 是大于 1.999.999。而如果两个 bundle 的版本信息,在前面的 3 个数字段都相同的时候,OSGi 就会对最后的字母段进行比较。而最后的字母段可以包含大写或小写的字母 A 到 Z、数字、连接线和下划线,所以它的比较比较复杂。OSGi 采用了标准 Java String 类的 compareTo() 方法的算法来进行比较,而标准 Java 的 String 类的 compareTo() 方法会对校正段的每一个字母按顺序进行比较,直到出现差异。另外如果字母相同,那么短的那个校正段的值将被认为小于长的校正段,beta_01 将会比 beta_010 小。
最后需要提的是 OSGi 不但可以为 bundle 指定一个版本信息,还可以为每一个类包指定一个版本信息,即 bundle 的版本控制是可以做到类包级别的(而且这是推荐的 OSGi 版本控制方式)。当 bundle 在 export 类包时,用户可以为每个类包指定一个版本信息。而当 bundle 需要 import 某特定版本的类包时,用户除了可以指定一个特定的版本信息外,还可以指定一个版本信息范围。而这个范围可以用方括号“【”和圆括号“(”来作为边界,方括号“【”表示边界值也在范围之内,而圆括号“(”则相反 . 比如说【 1.0.0,2.0.0)表示从版本 1.0.0 开始到 2.0.0 之间的所有的小版本,2.0.0 不在这个范围只内。下面是一些进一步的范围列表的例子,在下面的表 1 中 x 代表有效的范围列表:
[1.2.3,4.5.6) 1.2.3<=x<4.5.6
[1.2.3,4.5.6] 1.2.3<=x<=4.5.6
(1.2.3,4.5.6) 1.2.3<x<4.5.6
(1.2.3,4.5.6] 1.2.3<x<=4.5.6
[1.2.3,1.2.3] 1.2.3
1.2.3 1.2.3<=x
  0.0.0<=x

解释 WAS 在引入 OSGi 之后的类载入机制
OSGi 是如此优秀的一个框架,因此很多 Java 应用软件开始采用它,WebSphere Application Server(WAS)作为 IBM 最中要的 J2EE 服务器从版本 6.1 开始采用 OSGi 框架,因此当你的应用是基于 WAS 的并遇到了版本冲突问题,你就可以将你的应用转换成 OSGi 的 bundle,从而解决版本冲突问题。在将你的 WAS 的应用转变成 OSGi 的 bundle 之前,我们需要了解 WAS 是如何支持 OSGi 的,进而采取相应的行动。

图 3. WAS 从 6.1 以后的类加载器层次结构
图 3 是 WAS 从版本 6.1 以后的类加载器层次结构,从此图,我们可以知道 WAS 并不是完全采用 OSGi 框架(可能是出于向前兼容等因素考虑),IBM 只是将 WAS 的一部分变成了 OSGi 框架的类加载模式,而其他的部分继续延续了以前版本的类加载器层 次结构。而 WAS 中 OSGi 的那部分类加载器,以网关的形式与 WAS 的扩展类加载器连接在一起。
接下来,大家可能奇怪,WAS 原有的类加载器是如何同 WAS 中的 OSGi 部分的类加载器一起工作的呢? WAS 将如何进行类加载呢?
为了解释这个问题,我们首先要清楚,WAS 中的那一部分采用了 OSGi 的框架? WAS 将其常用的重要的插件部分做成了 OSGi,而所有的这些插件被放置在 WAS 的 plugins 目录中,因此 plugins 目录下的所有的插件是以 OSGi bundle 的形式被载入到 WAS 中来的。接下来,我将解释从版本 6.1 以后 WAS 将如何进行类加载。从图 3,我们可以得知,WAS 的 OSGi 框架是与 Ext 类加载器连接在一起的,这就是说 WAS 的 OSGi 框架在 WAS 整体的类加载器中处于一个很高的层次。而 Java 的类加载是采用父委托机制的,这就使普通的 WAS 上的应用程序会一层层的向上请求加载类,这样当某个特定的类在 WAS 的 OSGi 部分中被发现,那么 WAS 的类加载委托就会进入到 WAS 的 OSGi 运行时中。这样当这个类加载以后,而它又需要加载其他类时,这之后的类加载委托请求就会在 WAS 的 OSGi 运行时中相互传递。
由此可见,如果我们需要将自己的 WAS 上的应用程序转变成支持 OSGi,我们则需要将这个应用程序的模块转变成 OSGi bundle,然后将其放置在 WAS 的 plugins 目录下。


就职于IBM的OSGi CTO,BJ Hargrave曾在2009年三月撰文一篇,介绍了模块化的两个重要概念:可视性(visibility)和可用性(accessibility)的不同。以下为全文:
可视性指的是一个类型是否能看到另一个类型。在JLS(Java Language Specification,Java语言规范)当中,这个概念被当作可观察性(observability)被讨论。在JVMS(Java Virtual Machine Specification,Java虚拟机规范)当中,这个概念与类加载相关。基本上,这个概念描述出来就是:T类型对于S类型而言是否是可视的。在编译时,这个概念指编译器在编译S类型的时候能否为类型T定位。在运行时,这个概念指S类型的类加载器能否加载(直接的或通过委托的)T类型。一个类型也可以通过反射建立可视性。即使S类型的类加载器无法加载T类型,S类型仍然可以在反射时接触到T类型。比如说,一个对象是S类型通过I类接口直接引用的,但它仍然可能是T类型的对象。

可用性指的是一个类型能否使用(access)另一个类型,或另一个类型的成员。这在JLS和JVMS当中都进行过探讨。很多人通过public,protected和private关键字了解到可用性这个概念。
可视性和可用性的概念有重合,但他们是两个不同的概念;并且在我们实现Java模块化的时候,这两个概念必须要分开理解。首先,要使用一个类型,这个类型必须是可视的。然后才牵扯到这个类型或这个类型相关联的成员是否可用的问题。一个类型可以同时是可视的而不可用的。

OSGi通过严格限制可视性实现模块化。这很有道理,因为OSGi建立在类加载器(ClassLoader)模型之上。所以,如果bundle A导入了bundle B导出的包(packages),那么bundle B当中的其他所有包对于bundle A的类加载器而言都是不可视的。但是,如果bundle B注册了一个服务,而实现这个服务的类型对于bundle A的类加载器而言是不可视的,bundle A仍然能够得到这个服务的类对象(通过service.getClass())。即使那个类当中包含服务接口之外的公共方法(public methods),bundle A仍然可以呼叫这些方法。

困难在于模块之间界限的定义。

模块化编程最大的好处在于有效的控制和避免了模块被外部误用。其他方面的好处在于各模块可以方便的做到引用自己所需要依赖的包,避免产生包冲突现象,对于现有java体系而言,另外一个好处则是可以做到多版本的共存

模块化编程最大的难点一方面是设计方面的挑战,在没有实际隔离情况下模块化的设计其实并不会真正做到有效的模块隔离的设计;另一方面是在开发过程中,以前的开发习惯都需要改变,例如以前需要依赖其他模块时,可以采用直接依赖工程或依赖jar的方式,但在模块化的系统中则不行。
在实际的模块化开发过程中,更多的时间仍然会花费在设计阶段。

目前,有 4 种独立实现了的 OSGi 框架,他们分别是:
Equinox: 这个 OSGi 框架是目前应用最广泛的 OSGi 框架。它是由 IBM 开发的,目前已经被应用到 Eclipse,Lotus Notes,IBM WebSphere Application Server 等等。Equinox 实现了版本为 4.1 的 OSGi 规范。
Felix:这个 OSGi 框架实现了版本 4.x 的 OSGi 规范,它是由 Apache 开发和维护的。
Knopflerfish:这是一个流行并成熟的实现了版本 3 和 4.1 的 OSGi 规范的 OSGi 框架。它是由 Makewave AB 开发和维护的。
Concierge:这个 OSGi 框架实现了版本 3 的 OSGi 规范。


OSGi解决方案
每个模块都有自己独立的classpath
Java模块化不足问题的根源是那个全局的、扁平化的classpath;OSGi采取了一个完全不同的方法:每个模块都有自己独立的classpath。
OSGi采取了不同的类加载机制:
  • OSGi为每个bundle提供一个类加载器,该加载器能够看到bundle Jar文件内部的类和资源;
  • 为了让bundle能互相协作,可以基于依赖关系,从一个bundle类加载器委托到另一个bundle类加载器。
Java和J2EE的类加载模型都是层次化的,只能委托给上一层类加载器;
而OSGi类加载模型则是网络图状的,可以在bundle间互相委托。——这样更合理,因为bundle间的依赖关系并不是层次化的。
例如bundleA、B都依赖于bundleC,当他们访问bundleC中的类时,就会委托给bundleC的类加载器,由它来查找类;如果它发现还要依赖bundleE中的类,就会再委托给bundleE的类加载器

优点

  • 找不到类时的错误提示更友好。假如bundleE不存在,则bundleC就不会被解析成功,会有错误消息提示为何未能解析;而不是报错ClassNotFoundException或NoClassDefFoundError。
  • 效率更高。在标准Java类加载模型中,总是会在classpath那一长串列表中进行查找;而OSGi类加载器能立即知道去哪里找类。

解决模块化问题

  1. OSGi可以帮助你先确保代码满足依赖关系,然后才允许执行代码;避免类路径错误
  2. OSGi会对类路径上的依赖集进行一致性检查(如:版本);
  3. 不必担心由于层次化的类加载模式隐含的限制;——何种限制?
  4. OSGi可以把程序打包逻辑上独立的JAR文件,并且只部署指定的部分、动态部署;——OSGi生命周期层实现动态部署
  5. OSGi可以声明JAR中的哪些代码可以被其他JAR访问,强化可见性 ——OSGi中,只有那些被显式导出的包才能被其他bundle使用。也就是说默认情况下,所有包都是bundle private的,不能被其他包看到。
  6. OSGi为程序定义了一个插件式的扩展机制。




OSGi在项目的生命周期中,关注是否能积累重用稳定的代码,问题出现时能否隔断连锁反应蔓延,缺陷是否容易修复等。
  • OSGi会引导程序员开发出可积累可重用的软件。除常用的一些开源框架中,涉及到自己开发项目时也需进行可积累的设计。一种典型现象是项目中出现了一些“万能的包”,通常名字会是XXXCommons.jar,XXXUtils.jar等,这些包中存放了在项目中被多次调用的代码,但是这样的包不能叫做可重用包。当这些包越来越大、类别越来越多、功能越来越强时,与这个项目的耦合就越来越紧密,一般也就无法用在其他项目中了。如果某个模块有非常多的依赖项,那么没有人愿意为了使用其中少量功能去承担这些间接依赖的代价。因此设计者必须把模块设计的粒度合理,精心挑选对外发布的接口和引入的依赖,把每个模块视为一个商业产品来对待,这样才能积累出可重用的模块,也有利于提高程序稳定性。
  • 基于OSGi比较容易实现鲁棒性的系统。目前大多数系统做不到在某部分出现问题时隔离缺陷带来的连锁反应,如在项目中把Common Logging(或slf4j)的包拿掉,系统做不到只损失日志功能而其他部分正常运行。对于基于OSGi架构开发系统,在设计时自然会考虑到模块自治和动态化,如果软件在开发阶段跟随着OSGi的设计原则来进行,自然而然会实现强鲁棒性的系统。
  • 在OSGi环境下可以做到动态修复缺陷。许多系统都有停机限制,要求7*24小时运行,对于这类系统,OSGi的动态化能力在出现问题时就非常有用,可以做到不停机地增加或禁止某项功能、更新某个模块,甚至建立一个统一更新的模块仓库,让系统在不中断运行的情况下做到自动更新升级。

OSGi能让系统运行更快吗
OSGi框架对系统性能是有一定损耗的,首先,在系统执行方面,OSGi是在Java虚拟机之上实现的,它没有要求虚拟机的支持,完全通过Java代码实现模块化,在执行上不可避免地会有一些损耗。在服务层上,动态性(表现为服务可能随时不可用)决定了应用不能缓存服务对象,必须在每次使用前查找,这种对OSGi服务注册表的频繁访问也会带来一些开销。其次,从内存使用量来看,OSGi允许不同版本的Package同时存在,这是个优点,但是客观上会占用更多内存。在OSGi中只需付出一点Java方法去的内存即可解决。
仅从性能角度来说,OSGi确实会让系统性能略微下降,但是这完全在可接受范围之内。使用OSGi开发是应该考虑到性能的影响,但不应当将其作为是否采用OSGi架构的主要决策依据。

OSGi能支撑企业级开发吗
在企业级OSGi出现之前,企业级开发要么是走Java EE的重量级路线,要么是走SSH的轻量级路线。企业级OSGi被引入后并没有扮演一个“革命者“的角色,没有把Java EE或SSH中积累的东西推翻重来,OSGi更像是扮演一个”组织者“的角色,把各种企业级技术变为它的模块和服务,使之前的企业级开发技术在OSGi中依然能够发挥作用。

OSGi的本质是将Java面向对象的开发转向面向组件和服务的开发。OSGi框架提供了一套完善的机制用于管理和控制组件(Bundle)、服务(Service)的生命周期,以及组件和服务在其生命周期内的交互。
实现了OSGi的开源的Eclipse Equinox,Apache Felix和Knoplerfish框架
OSGi规范为Java定义动态模组元信息系统和在其交互模组中的面向服务的编程模型。这个规范定义了一个为服务查找的注册表,还定义了一组通用功能集合,例如安全,生命周期管理,日志等。OSGi的框架如今已经被Eclipse基金采用,许多的主要Java厂商采用这个规范来开发中间件产品,同时OSGi也被很多开源项目组采用,包括用来开发应用服务器,企业服务总线,和集成开发环境。

OSGi规范并不是单一的规范文档,而是由一系列子规范构成,这些子规范主要可分为两大部分,其中一部分用于描述OSGi的核心框架(OSGi Framework)。OSGi核心框架是一个可运行OSGi系统的最小集合,它由以下内容组成:

  • 执行环境(Execution Environment)。由于OSGi所适用的目标范围非常广泛,为了更好地处理不同硬件、软件环境对OSGi造成的兼容性问题,在建立其他约定之前,必须先定义好系统的执行环境。
  • 安全层(Security Layer)。描述了基于Java 2安全架构实现的代码验证、JAR文件数字签名、数字证书服务,安全层贯穿了OSGi框架的其他各个层次。
  • 模块层(Module Layer)。模块层从“静态”的角度描述了一个模块的元数据信息、执行环境定义、模块约束和解析过程、类加载顺序等内容。模块层是整个OSGi中最基础、最底层的层次。
  • 生命周期层(Life Cycle Layer)。生命周期层从“动态”的角度描述了一个模块从安装到被解析、启动、停止、更新、卸载的过程,以及在这些过程中的事件监听和上下文支持环境。
  • 服务层(Service Layer)。描述了如何定义、注册、导出、查找、监听和使用OSGi中的服务。服务层是所有OSGi标准服务的基础。
  • 框架API(Framework API)。由一系列通过Java语言实现的接口和常量类构成,为上面各层提供面向Java语言的编程接口。

构成OSGi规范的另外一部分内容是OSGi标准服务,这些标准服务试图以OSGi为基础,在软件开发的各种场景中(如配置管理、设备访问、处理网络请求等),建立一套标准服务和编程接口。软件开发所遇到的场景是多种多样、极其复杂的,因此OSGi对应定义的标准服务也非常庞大和复杂,OSGi所包含的数十个子规范大部分都用于定义这些标准服务。以下列举了一小部分较为常用的OSGi标准服务。

  • 事件服务(Event Admin Service)
  • 包管理服务(Package Admin Service)
  • 日志服务(Log Service)
  • 配置管理服务(Configuration Admin Service)
  • HTTP服务(HTTP Service)
  • 用户管理服务(User Admin Service)
  • 设备访问服务(Device Access Service)
  • IO连接器服务(IO ConnectorService)
  • 声明式服务(Declarative Services)

0 0
原创粉丝点击