`

OSGi概念入门

阅读更多

OSGi概念入门

 

OSGi概念入门

OSGi 是什么, OSGi 是一种服务运行平台。通过实现能够提供服务的符合 OSGi 规范的组件,用户可以将其组件发布到 OSGi 运行平台,供用户和其他组件使用。 OSGi 组件提供的服务具有两个层面的含义:系统层面,即一个组件为其他组件提供服务,这些服务体现为 Java 接口的实现;业务层面,即一个组件为外部系统或用户提供某种业务服务实现。

OSGi 是什么

OSGi 是什么, OSGi 是一种服务运行平台。通过实现能够提供服务的符合 OSGi 规范的组件,用户可以将其组件发布到 OSGi 运行平台,供用户和其他组件使用。 OSGi 组件提供的服务具有两个层面的含义:系统层面,即一个组件为其他组件提供服务,这些服务体现为 Java 接口的实现;业务层面,即一个组件为外部系统或用户提供某种业务服务实现。

OSGi 提供的功能

OSGi 能够提供什么功能呢?我们将 OSGi 运行平台与常用的 Web 应用服务服务器做一个比较,来看 OSGi 提供的功能。首先,以 tomcat 为例,在 tomcat 容器中可以运行多个 Web 应用,假设存在两个 Web 应用 A Web 应用 B ,一般说来, Web 应用 A B 具有各自的运行空间,两者之间不存在任何关联, A B 具有自己独立的生命周期,如部署、启动、停止和卸载等。

那么,是如何做到这一点的呢?很明显,这是通过 JVM 的类加载机制决定的。当 tomcat 运行并启动 Web 应用 A B 时, tomcat Web 应用 A B 各自构建了一个类空间,也可以看作是一个类域( Class Domain ), Web 应用 A 的类域包括 JRE 中的类, tomcat 启动类路径上的类和 Web 应用 A WEB-INF 目录下 classes 目录下的类和 lib 中的 jar 包;同样, Web 应用 B 也有自己独立的类域,其范围除了 JRE 中的类, tomcat 启动类路径上的类之外就是自己内部 WEB-INF 目录下 classes 目录下的类和 lib 中的 jar 包。现在提出一个问题,如果 Web 应用 A 需要使用 Web 应用 B 提供的 Java 类,怎么办?实现方式有多种,一种是将 B 提供的类打包,放置到应用 A WEB-INF/classes WEB-INF/lib 中;也可以将 B 提供的类放置到 tomcat 的类路径上,甚至是 JRE 的扩展目录下,但这样做在实际使用中或多或少存在一些问题。能不能在运行时 Web 应用 A 可以直接使用 Web 应用 B 提供的类呢?在运行时 Web 应用 B 能不能提供一个接口的实现,即类实例,由 Web 应用 A 使用呢?能不能提供一个应用 C 为应用 A 和应用 B 提供服务呢?显然,这些对于 Web 容器是不行的。

带着上述问题我们回到 OSGi 运行平台。可以将 OSGi 看作是 Web 容器的泛化,是更高级别的抽象。运行在 OSGi 环境中的类似于 Web 容器中的 Web 应用的组件即 Bundle ,不再仅仅局限于一个业务应用的概念,它的粒度更加精细,即可以看作是一个 Jar 包,为其他 Bundle 提供帮助类;也可以是一个 HTTP 服务组件,为其他 Bundle 提供 http 服务;还可以是一个 Web 容器,为其他 Bundle 提供 Web 应用服务。

那么,能不能解决上述提到的问题呢?我们假设在 OSGi 运行平台中包含了 3 Bundle A B C 。对于问题一: Bundle A 需要使用 Bundle B 中的某些实现类,如何实现?可以将 Bundle B 中的这些类通过 Bundle B 的元数据描述信息公开( Export )出去,使得这些类对 OSGi 平台中的所有 Bundle 可见,这些类资源仍然位于 Bundle B 中。 Bundle A 在其元数据描述信息中将 Bundle B 公开的类引入( Import )进来。在运行时, Bundle A 就可以使用 Bundle B 提供的这些类,而不是需要将这些类拷贝到 Bundle A 中或其他位置。对于问题二: Bundle A 可不可以直接使用 Bundle B 在运行时构建了类实例? Bundle B 在运行时可以将 Bundle A 需要的类实例注册到 OSGi 运行平台的服务注册表中,类实例实现的接口可以通过上述问题一的方式使得 Bundle A 可见,那么,在运行时, Bundle A 就可以通过该接口到 OSGi 平台服务注册表中查找 Bundle B 中提供的接口实现类实例,并调用该接口上的方法。现在来看问题三: Bundle C 能不能为 Bundle A Bundle B 共享呢?可以将上述问题二的解决方案中的 Bundle B 提供的接口定义提取到 Bundle C 中,并在 Bundle C 的元数据中公开,通过在 Bundle A Bundle B 中同时引入 Bundle C 中发布的接口, Bundle B 提供该接口的实现, Bundle A 使用该接口实现提供的功能。这一切看上去是不是解决的非常完美呢?!

OSGi 的实现机制

OSGi 是如何实现的呢?从本质上说, OSGi 是充分使用了 Java 的类加载机制,对模块和应用进行了更加精细粒度的控制,然后在类域上建立一系列松耦合应用。 OSGi 为每一个 Bundle 组件定义了一些元数据信息,通过这些元数据, OSGi 在运行时为每一个 Bundle 构建了一个独立的类域(即类空间),详细描述参考 OSGi Bundle 小节。

OSGi 的组成

OSGi R4 种将功能分为几层,包括:安全层、模块层、生命周期层、服务层和实际的服务。 OSGi 的核心实现即为 OSGi 框架,它本身也是一个 OSGi Bundle

u OSGi 的安全层( Security Layer )是一个可选的实现,该层基于 Java2 安全架构,位于 OSGi 服务平台的底层对 OSGi 环境中应用的部署和管理提供更好的安全控制。

u OSGi 的模块层( Module Layer )为基于 Java 的应用、组件的打包,部署和校验提供了一个通用的标准化的解决方案。其他类似的解决方案如 JBoss NetBeans

u 生命周期层( Life Cycle Layer )为 Bundle 组件的安全和生命周期操作提供了 API 定义,该层位于安全层和模块层之上。

u 服务层( Service Layer )定义了一个与生命周期层紧密结合的组件动态交互模型。 OSGi 中的服务是实现了一个或多个 Java 接口的 Java 对象,通过将这些对象依据其实现的接口注册到服务注册表中, Bundle 组件可以发布自己的服务,查找使用服务,注册监听处理服务的状态变更等。

u 实际的服务( Actual Services )是 OSGi 定义的一些标准的服务接口如日志服务( Log Service ),包管理服务( Package Admin Service )、启动级别服务( Start Level Service )、 HTTP 服务( Http Service )、配置服务( Config Admin Service )、用户管理服务 (User Admin Service) 等等,详细的服务定义参考 OSGi 规范。

OSGi Bundle

OSGi 中的重要元素就是 Bundle Service Bundle 提供了一种静态资源边界,类似于 Web 容器中的 Web 应用的概念。

每一个 Bundle 通过一个元数据文件( MANIFEST.MF )描述。 OSGi 框架(即 SystemBundle )通过解析这个元数据文件对该 Bundle 进行加载和管理。 Bundle 通过元数据中的 "Export-Package" 属性将内部的类包发布给 OSGi 系统中其他 Bundle 使用,通过 "Import-Package" "Requie-Bundle" 属性引用 OSGi 系统中其他 Bundle 发布的类包。

每一个 Bundle 有自己独立的类加载器( Fragment Bundle 例外,其资源通过其 Host Bundle 加载), Bundle 内部的资源(类,文件等)通过该类加载器查找和加载。 Bundle 的类加载器能够控制的类加载边界包括:启动类路径上的类资源, OSGi 框架即 SystemBundle 上的类资源和 Bundle 内部的类资源。该类资源边界即形成该 Bundle 的类域。

每一个 Bundle OSGi 框架中具有自己的生命周期,其生命周期内的状态包括: INSTALLED RESOLVED STARTING ACTIVE STOPPING UNINSTALLED

INSTALLED 状态是 Bundle 的初始状态,当该 Bundle 部署到 OSGi 系统的 Bundle Repository 中时, Bundle 的状态标记为 INSTALLED

Bundle 内部的资源在加载之前,首先由 OSGi 框架对其进行解析( Resolve ),解析的过程就是分析 Bundle 的元数据的过程,详细过程参考 OSGi 规范。解析后的 Bundle 进入 RESOLVED 状态,解析失败时,仍然处于 INSTALLED 状态。

Bundle 内的资源被其它 Bundle 使用时,该 Bundle 被启动,也可以通过设定让 OSGi 框架在加载该 Bundle 时直接启动。

Bundle 内的资源通过 BundleContext 与其他 Bundle 进行交互。元数据中的 "Bundle-Activator" 属性指定了实现 BundleActivator 接口的实现类, Bundle 通过该类得到 BundleContext ,通过 BundleContext 可以查找其他的 Bundle ,查找注册在 OSGi 中的服务( Service )与 OSGi 环境进行交互等等。 Bundle 可以在其提供的 BundleActivator 实现类中进行初始化的工作,也可以注册服务到 OSGi 的服务注册表中,供其他 Bundle 查找使用。

开源的 OSGi 实现

Knopflerfish

http://www.knopflerfish.org

Oscar

http://oscar.objectweb.org

Equinox

http://www.eclipse.org/equinox

Flex

http://incubator.apache.org/flex

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics