OpenDoc Series':OSGI实战(八)

 由  ValRay 发布

八. 应用 OSGI

之前的章节中对于 OSGI 的应用都只是让大家对于 OSGI 的实战有个较为实际的概念,并没有在整个系统级别去应用 OSGI,要在整个系统级别上应用 OSGI,还是会带来不少的挑战的,但相对于 OSGI 能带来的优势,相信这是值得的,在应用 OSGI 时应大程度的发挥基于 OSGI 搭建系统的优势以及减少基于 OSGI 系统带来的挑战。 由于基于 OSGI 搭建系统带来的是架构级别的改变,带来的大的影响莫过于设计层面,同时对于系统开发和部署也产生了影响。

先说说设计层面的,主要是模块化设计、面向服务的组件模型设计以及动态性的设计三个方面,也只有在把握好了这三方面才能充分的发挥基于 OSGI 搭建系统的优势,否则也许会给项目或产品带来更大的痛苦。

8.1. 模块化设计

尽管大家在设计大部分的系统时候确实是按照模块化的思想去进行的,但可能不会考虑的象 OSGI 定义 Bundle 那么的清晰,但这点相信大家都能很快的适应,毕竟模块化的思想大致仍然是相同的,基于 OSGI 就可以按照统一的标准进行模块的设计,同时也会提升在模块设计时对于模块的输入(依赖) 、输出(功能)、扩展的关注,从而使得模块的设计更加的完善和规范。

基于 OSGI 搭建的系统架构通常类似如下:

图表 12 基于OSGI搭建的系统架构示意图

可以看出基于 OSGI 搭建的系统由 Bundle 组成,而每个 Bundle 由多个 Component 或 Java Object共同组成,每个Component又有可能引用或暴露了多个Service,每个Bundle 以及 Component 均可在其生命周期状态改变时做出相应的行为。

8.2. 面向服务的组件模型设计

模块化设计可以看成是架构级别的设计方式,而面向服务的组件模型设计则是对模块 进行详细设计时的核心思想了,在 OSGI 中的模块划分为不同的 Component 和 Java Object 共同组成,Component 和普通 Java Object 不同的地方在之前的章节中已经做过解释了,在这就不多说了,Component 通过引用 Service 或暴露 Service 来完成模块中用例的实现,应该说,这种方式和传统的设计方法也没有太多的差别,面向服务的组件模型设计更加强调在设计时分解模块中用例的实现(形成组件和服务)以及组件依赖的关注。

基于 OSGI 框架构建模块、Component、Service 的依赖时,体现出了超越传统 IoC 容器的优势,在依赖的构建上 OSGI 更是提供了多种灵活的依赖控制方式,例如属性过滤、版本过滤以及延迟加载设置等。

8.3. 动态性设计

从 OSGI 规范的定义来讲,基于 OSGI 搭建的系统保持动态性是其大的优势,包括 模块、Component、Service 的依赖都具备动态性的特征,在构建模块、Component、 Service 的依赖时 OSGI 框架采用的都是动态的方式实现,这也就是说 OSGI 框架本身保证了基于其实现的系统的动态性,但这并不意味着基于 OSGI 框架实现的系统就一定具备动态性特征,就像基于 JAVA 编写的系统不一定跨平台一样。

要充分的发挥基于 OSGI 的动态性,就要完全的采用面向接口的设计方式,而不是去依赖实现,要记住基于 OSGI 搭建的系统是在运行期才构成依赖的,这和传统的系统有很大的差别,所以在设计基于 OSGI 的系统时特别要注意依赖不要在设计时就定死,而应该在运行期由 OSGI 框架自动的注入。

OSGI 提供的对于依赖的各种管理策略(如版本过滤、多样性设置等)在保证系统动态性的同时也保证了系统获取到所需的模块、Component 或 Service。

8.4. 面向接口的开发

基于 OSGI 能让我们在开发时真正的做到面向接口的开发,尽管面向接口的开发的思想已经被几乎所有的开发人员所接受,但由于有些时候偷懒或者无意中就直接去引用了实现的类,尽管象 A a=new AImpl()这样的代码在 Factory 模式、IoC 容器得到认同后出现的已经很少了,但无论是采用 Factory 模式还是 IoC 容器都是在设计期隐性的对实现设置了直接的依赖,而非运行期去寻找可用的依赖的,而同样由于 A a=new Aimpl()还是可以直接的写,导致了有些时候还是会出现这样的强制依赖的代码,而 OSGI 提供为每个 Bundle 提供独立的 ClassLoader 机制的方法则让我们可以真正的做到面向接口的开发,Equinox 本身就给出了一个这样的例子,在 Equinox 中将 OSGI中所有服务的接口都统一放到了 OSGI Services Bundle 中,由该 Bundle 对外 Export 这些 Packages,而对于这些 Service 的实现则由其他单独的 Bundle 去实现,那些 Bundle 就无需对外提供 Package 了,这样就真正的隐藏了接口的实现,而加上 OSGI 的动态性,使用这些接口的类也只有在被使用的时候才会寻找相应可用的依赖,所以在基于 OSGI 框架进行开发时应该养成对外 Export 接口的 packages,而隐藏实现接口的 packages,更为好的方法就是把接口单独的放入一个 Bundle 中,这样对于更换接口的实现就更为方便了。

对于系统开发方面,产生的影响主要是让单元测试显得更为重要了,毕竟所有的依赖都是动态设置的,要依靠集成测试来发现问题就显得更为麻烦了,所以基于 OSGI 的系统会更多的依赖 Mock 进行单元测试,其他的影响就是不再通过引用 lib 或 project 的方式来设置对于其他工程的依赖等等。

对于系统部署方面,产生的影响是现在的部署是多工程共同部署的方式,这个时候自动化的部署脚本就显得非常有必要了。

在 OSGI 应用的好的情况下,基于它搭建的系统应具备统一的模块化构建和管理、可插拔、可积累以及可动态改变和扩展行为的特征。

九. OSGI 资源

OSGI目前国内的资源相对还是比较的少,国外的资源主要是OSGI的官方网站、Equinox 网站以及其他的一些开源 OSGI 框架(例如 Oscar、Knopflerfish)的网站。

  • 网站

中文方面的主要有www.riawork.org

英文方面的主要有www.osgi.org、www.eclipse.org/equinox - Blog

OSGI官方Blog:www.osgi.org/blog

OSGI主席Peter的Blog:www.aqute.biz

  • 邮件列表 Equinox 邮件列表以及 OSGI 官方的邮件列表。

十、OSGI 框架前瞻

从基于 OSGI 框架搭建应用系统级别的视角来看目前的 OSGI 框架在这几方面还需要进一步改进:

  • 对于 B/S 结构系统支持的不足

目前的 OSGI 框架对于 B/S 结构的系统支持仍然显的非常的不足,这点也是现在 Equinox 的重要提升点,考虑如何更好的和应用服务器的集成是 Equinox 的重点,一定程度上这也会影响到 equinox 的接受度,毕竟目前大部分的系统都是 B/S 结构的。

  • 管理端不够强大

目前 OSGI 框架提供的管理端不够强大,现在的管理端中仅提供了基本的 Bundle 状态管理、日志查看等功能,象动态修改系统级别的配置(config.ini)、动态修改 Bundle 的配置(Manifest.mf)、启动级别等功能都尚未提供,而这些在实际的项目或产品中都是非常有必要的。

  • 缺少基于微核统一管理应用系统的功能

基于微核统一管理应用系统是指可以通过微核来统一控制应用系统的启动、停止或更新,在这样的情况下,只要微核的运行是稳定的,那么系统就可以一直的处于运行状态,对于用户而言从项目启动的那天就可以看到一个在不间断运行的系统。

至于框架中缺少构建应用级别系统的通用 Bundle 的这个问题,倒是可以通过依靠大家的力量来完成,大家可以把在项目中使用的象持久层处理 Bundle、缓存处理 Bundle 等等贡献出来。

十一.OSGI 带来的遐想

基于 OSGI 搭建系统带来了不同的系统设计和开发的方式,OSGI 可以带动 Java 界模块化级别设计思想的统一,这点已经得到了证明,尽管 JSR277 目前未接受 OSGI 作为其规范,但 OSGI 带来的影响是必然的,也许在以后的某个 Java 版本发布的时候,大家就会按照同样的方式去设计模块以及模块间的依赖,编写模块中的 Component 和 Service,也许以后可以从网站上下载各种各样的 Bundle,从而搭建成自己所需要的系统,而每个公司在搭建自己新项目的脚手架甚至是原型系统时,可以直接从公司的 Bundle 库中获取相应的 Bundle 来搭建,对于公司的积累而言,无疑这是非常有利的。 基于 OSGI 的 C/S 结构的系统也许就能做成象硬件一样卖给用户,甚至可以同样的提供象路由器中一样的热插拔式的硬件模块,又或者可以采用 Server 端统一管理 Client 端功能模块的方式,由 Server 端分发、更新 Client 端的功能模块。

基于 OSGI 还会给我们带来更多更大的惊喜,都等待着大家一起去发掘…….

十二.参考文献

查看评论