- 1 -
基于 OSGi架构的面向服务组件编程
赵林虎
北京邮电大学计算机科学与技术系,北京(100876)
摘 要:OSGi(Open Services Gateway Initiative,开放服务网关协议) 提供了一个面向服务组
件编程模型。通过 OSGi 框架可以轻松构建组件,同时组件与组件之间实现了信息的隐藏
和共享。由于 OSGi框架具有模块化,标准化,面向服务,动态性,易复用,易扩展,易
部署等诸多优点。并随着 Eclipse的成功应用,已经获得越来越多的 IT厂商的支持,并已
经成为基于组件开发的事实上的工业标准。本文主要探索如何在 Eclipse环境下开发面向服
务组件。
关键词:OSGi;组件;Eclipse;Equinox
1 引言
OSGi [1~2]联盟建立于 1999 年,是一个非赢利机构,旨在建立一个开放的服务规范。
OSGi 规范为网络服务定义了一个标准的、面向组件[3]的计算环境,它最初的目的就是为
各种嵌入式设备提供通用的软件运行平台,屏蔽设备操作系统与硬件区别的中间件平台,
通过这个平台,可以对不同软件商提供的应用(OSGi 中称为 Bundle[3])进行组件的生命周
期管理的能力,如应用组件可以从运行中被安装、升级或者移除而不需要中断设备的操作,
应用组件可以动态的发现和使用其他库或者应用程序。由于 OSGi 技术具有服务组件模块
化、动态加载应用等优点,正被越来越多的领域关注,如嵌入设备制造业、汽车制造业、
企业应用等。
从技术层次上看,OSGi 的服务网关实际上是嵌入在连接外部服务和内部服务的网络
中的内嵌式服务器。其核心技术是 Java, 特别是 Java 虚拟机(JVM)。由于采用了 Java[2]
技术作为基础,OSGi 服务网关不仅具有独立于不同制造商,并且可以通过 API 整合不同
的标准的特点。它主要具有如下优势[5]:1)基于 OSGi 的应用程序可动态更改运行状态和
行为。2)它是一个稳定高效的系统。3)提高了组件的可复用能力,提升了系统开发效率,
降低了开发成本。
2 系统背景及模块介绍
OSGi 带来了规范化的模块划分,低耦合的模块间关系,统一的模块开发方式,可动
态插拔的模块管理环境。开发 OSGi 应用程序的第一步是在需求分析的基础上进行精心的
模块划分,模块划分的原则是尽量保持单个模块的独立性,使模块与模块之间的耦合降到
最小,每一个模块暴露给其它模块的信息最少,尽量让模块之间使用 OSGi 框架提供的服
务注册机制来通信。一般可采用一个模块一个 Bundle 的方式,并为每一个 Bundle 在
Eclipse 环境中建立一个 Project 来进行开发,由于模块与模块之间的耦合很小,各个
Bundle 之间并不会象传统的开发方式中的各模块之间那样存在纠缠不清的包和类的引用
关系,因此大部分 Bundle 的开发工作可以并行进行而不会互相影响。
本文设计并实现了简单的电子购物模块,并对其中相关的模块进行了高度抽象,提炼
出 OSGi 最核心的模块,以使读者能更加容易的理解 OSGi 的开发部、部署以及管理流程。
本系统主要由以下模块组成:
z 抽象服务 Bundle:我们通过将服务定义为接口,并将接口发布给客户,这样提高
中国科技论文在线
- 2 -
了系统的可扩展性
z 服务提供者 Bundle:通过扩展接口,实现具体服务的组件,同时允许不同的组件
以不同的方式实现接口组件中定义的服务。
z 服务消费者 Bundle:使用接口中定义的服务,并可动态绑定到不同的服务提供者
Bundle。
3 系统开发环境
本系统基于Eclipse的Equinox[5]框架。Equinox是OSGI R4的一个实现它是由Eclipse
开源组织实现并发布的,同时也是 Java 开发工具 Eclipse 的底层机制的实现。Equinox 的
OSGi 核心实现由三部分组成,包括:OSGi 核心规范的实现(),OSGi 框
架启动支持()以及 Equinox 启动可执行程序。Equinox 为我们
提供了强大的组件开发环境,它使得我们开发具体组件的工作变得更加便捷和高效。
4 系统设计与实现
1) 实现 Service Bundle
新建 Eclipse plugin-in project,并将其命名为 , 注意创建 OSGi
Bundle 工程时,一定要选中“an OSGi framework”做为工程的目标平台,并选择 Equinox 或
standard,这两个选项的区别是:Equinox 对 OSGi 规范第 4 版进行了一些扩展,如果开发
出来的 Bundle 希望能够在其它的 OSGi 实现框架如 Oscar,Knopflerfish 上顺利运行,此处
最好选择 standard。这个 Bundle 的实现很简单,它无需实现 BundleActivator 类,只需定义
一个接口即可:
代码清单 1:
package ;
public interface IProductService {
public String getProductMessage();
}
同时将 Bundle 的 文件中将相应的 package 导出
代码清单 2:
Manifest-Version:
Bundle-ManifestVersion: 2
Bundle-Name: Services Plug-in
Bundle-SymbolicName:
Bundle-Version:
Bundle-Vendor: BUPT
Bundle-RequiredExecutionEnvironment:
Export-Package:
中国科技论文在线
- 3 -
2) 实现服务提供者 Bundle
新建一个 Eclipse plug-in project,将其命名为 ,此 Bundle 负责生成
向客户提供 HP 的产品,它需要实现 service bundle 提供的 IProductService 接口,同时在其
文件中导入相应的包来向 OSGi 框架注册服务。
代码清单 3:
Manifest-Version:
Bundle-ManifestVersion: 2
Bundle-Name: Hpfactory Plug-in
Bundle-SymbolicName:
Bundle-Version:
Bundle-Activator:
Bundle-Vendor: BUPT
Bundle-RequiredExecutionEnvironment:
Import-Package: ,
;version=""
此 Bundle 主要负责两方面的工作:一个实现 IProductService 接口的类,用于向客户提
供服务,另一方面用于在 Bundle 启动时向 OSGi 框架注册服务,同时在 Bundle 停止时注
销服务。(代码清单如清单 4 所示)。
代码清单 4:
package ;
import ;
public class HPProductService implements IProductService {
@Override
public String getProductMessage() {
return "PC From HP Company";
}
}
代此码仅为演示用途,实际项目中会比这复杂。但若代码过于复杂,掩盖了 OSGi 的
本质,因此再此略过。
代码清单 5:
package ;
import ;
import ;
import ;
中国科技论文在线
- 4 -
import ;
import ;
public class Activator implements BundleActivator {
private BundleContext context = null;
private ServiceRegistration serviceRegistration = null;
public void start(BundleContext context) throws Exception {
= context;
IProductService factory = new HPProductService();
Properties properties = new Properties();
("company", "HP");
serviceRegistration = (
.getName(), factory, properties);
}
public void stop(BundleContext context) throws Exception {
();
context = null;
}
}
代码清单 5 中最重要的功能就是向 OSGi 框架注册了 ProductService 服务,注册时使用
了一个 Properties 容器,容器中的 Key-Value 对说明了当前这个服务时来自于 HP 公司。其
他公司也可实现类似的 Bundle 来提供不同的服务,其过程与
完全类似,在此不再累述。
3) 实现服务消费者 Bundle
新建一个 Eclipse plug-in project,将其命名为 .它调用服务提供者提供
的服务。首先需要在 文件中导入相应的包:
代码清单 6:
Manifest-Version:
Bundle-ManifestVersion: 2
Bundle-Name: Client Plug-in
Bundle-SymbolicName:
Bundle-Version:
Bundle-Activator:
Bundle-Vendor: BUPT
Bundle-RequiredExecutionEnvironment:
Import-Package: ,
;version="",
;version=""
中国科技论文在线
- 5 -
此 Bundle 主要包含三部分工作:一个 ServiceTracker 类,用于监视服务提供者 Bundle
注册的服务是否可用(如代码清单 7 所示)。一个后台控制线程,用于循环执行服务提供
者提供的服务(如代码清单 8)所示。一个 Activator 类用于在 Bundle 启动时启动
ServiceTracker 服务,并在 Bundle 停止时停止 ServiceTracker 服务(如代码清单 9 所示)。
代码清单 7:
package ;
import ;
import ;
import ;
import ;
public class ProductServiceTracker implements ServiceTrackerCustomizer {
private BundleContext bc;
private ConsoleThread thread;
public ProductServiceTracker(BundleContext bc, ConsoleThread thread) {
= bc;
= thread;
}
@Override
public Object addingService(ServiceReference reference) {
IProductService service = (IProductService) (reference);
(service);
return service;
}
@Override
public void modifiedService(ServiceReference reference, Object serviceObject) {
IProductService service = (IProductService) (reference);
(service);
}
@Override
public void removedService(ServiceReference reference, Object serviceObject) {
IProductService service = (IProductService) (reference);
(service);
return;
}
}
中国科技论文在线
- 6 -
代码清单 8:
代码清单 8 是一个多线程程序,为演示之简便,在此例中它只是用一个 HashSet 持有
当前可用的服务,并无限循环,依次执行各项系统服务。在实际情况中,完全可以与用户
交互,根据用户的指令来执行相应的系统管理服务。
代码清单 9:
package ;
import ;
import ;
import ;
import ;
public class Activator implements BundleActivator {
private BundleContext context = null;
private ServiceTracker tracker = null;
private ConsoleThread thread = new ConsoleThread();
public void start(BundleContext context) throws Exception {
= context;
tracker = new ServiceTracker(context, (),
new ProductServiceTracker(context, thread));
();
();
}
public void stop(BundleContext context) throws Exception {
();
();
}
}
5 运行以及测试基于 OSGi 的应用程序
一个基于 OSGi 的应用程序是由 OSGi 框架本身以及若干个 Bundle 组成,为了对其进
行运行和测试,通常需要将各个 Bundle Project 一一打包成 Bundle(jar 文件),并部署到一
个 OSGi 框架中,还是比较麻烦的。幸运的是,Eclipse 已经对此提供了很好的支持,Eclipse
本身是基于 OSGi 框架 Equinox 的,在 Eclipse 环境中可直接将各 Bundle 部署到 Equinox
框架中并运行之,对开发者来说十分便利,其具体步骤如下:
在 Eclipse 中选择 Run-->Run...菜单,在弹出的 Run 配置面板的左侧选中“Equinox OSGi
Framework”,然后再选择其上方的 “New”按钮创建一个新的运行配置,将其命名为
“productmanagement”,再选择右侧的 Deselect All 按钮,然后只选择我们想要运行的 4 个
Bundles:包括我们前面开发的 3个Bundle以及OSGi框架本身 ,其中还可以设
中国科技论文在线
- 7 -
置各个 Bundle 的 Start Level, Start Level 可用于控制各 Bundle 的启动顺序,Start Level 低的
Bundle 会优先启动,如下图 1 所示:
图 1:OSGi 应用程序程序运行配置
Eclipse 环境中的运行结果如下图 2,在控制台中会不断的显示一些系统管理信息,同
时也可在控制台中运行各种 OSGi 控制台命令,如 ss 命令可用于显示各 Bundle 的状态,同
时可以通过 help 命令了解更多的 OSGi 控制台命令。
图 2:OSGi 应用程序运行界面
6 体验 OSGi 动态性
除了模块化以及面向服务编程之外,OSGi 的另一个重要特点是其动态性,Bundle 以
及 Bundle 提供的服务可以随时消失或者重新加入,而其它使用服务的 Bundle 可以感知服
务是否可用,并动态地改变自己的行为。应用程序在运行过程中,可以随时增加新的 Bundle,
停止或卸载已有的 Bundle,如果有新的服务加入进来,这个服务也能立即被其它 Bundle 使
中国科技论文在线
- 8 -
用并由此动态地改变整个应用程序的行为,在整个动态改变的过程中,OSGi 框架本身是稳
定的,无需重启。以下我们将通过一些示例来体验 OSGi 的动态性。
现在 Dell 公司也提供了类似的产品服务,而作为客户也希望将已有产品替换成 Dell
公司提供的产品。我们只需在命令行下通过简单的命令就可实现,而无需重启已有的项目,
这真正实现了软件的“热插拔”。
操作过程如下图 3 所示,同时我们在表 1 中列出了常用的 OSGi 命令。
图 3:动态加载及启动 Bundle
表 1. 有用的控制台命令
install 为当前实例添加一个给定了 URL 的 Bundle
uninstall 删除当前实例的具有给定 URL 的 Bundle
start 启动给定了 ID 或符号名称的 Bundle
stop 停止给定了 ID 或符号名称的 Bundle
update 为当前实例更新给定 URL 的 Bundle
ss 列出在当前实例中注册的所有 Bundle 的简短状态
7 结束语
由于基于 OSGi 的应用程序具有高度的模块化和动态性的特点,使得要对其进行扩展
也变得非常的方便:一般来说,扩展就是增加新的 Bundle,对其它 Bundle 基本无影响,如上
面的例子所示,我们很方便地为应用程序增加了新的功能,更新了它已有的功能,而整个
应用程序甚至都不需要重启。Equinox 同时还借用了 Eclipse 中的扩展点的机制,利用扩展
中国科技论文在线
- 9 -
点,可以方便的为已有的 Bundle 扩展功能。基于组件或构件编程是学术界提了多年的思想,
而 OSGi 是一个比较彻底地体现这种思想的编程模型,基于 OSGi 编程将带来软件设计以
及开发方式的改变并由此带来软件生产效率的极大提升。
参考文献
[1] OSGi Service Platform R4 [EB/OL]
[2] Java Community Process[EB/OL]
[3] OSGI Component Programing[EB/OL]
[4] Getting started with OSGi [EB/OL]
[5] BJ Hargrave, Peter Kriens . OSGi Best Practices[EB/OL]
SOA Component Programming Based On OSGi
Framework
Linhu Zhao
Beijing University of Posts and Telecommunications, Beijing (100876)
Abstract
OSGi (Open Services Gateway Initiative) provides a service-oriented component programming model.
Through the OSGi framework,we can easily build components, and at the same time, information
of different components can be hidden and be shared. OSGi framework have modular, standardized,
service-oriented, dynamic, easy to reuse, easy expansion, easy deployment and many other advantages.
And with the success of Eclipse applications, there are more and more IT vendors to support it. Also it
has become the defacto industry standard. In this paper, I will explore how to develop service-oriented
component in Eclipse environment.
Keywords:OSGi Component; Eclipse; Equinox
中国科技论文在线