基于Equinox开发OSGi应用(二)

上接   基于Equinox开发OSGi应用(一)

 

开发一组计算器bundle实例

      本节讲到的例子是仿照网上甚为流行的一个例子,但苦于一直未找到源码,网上贴的都是一些转帖,代码片段,估计初学者很难将其还原并调通!我最开始弄这个咚咚的时候,其过程之痛苦,难以言喻,所以想着仿照该例子的设计,给予实现,文后贴出源码,希望能帮到大家。

         该例子是一个关于计算器的实例,osgi.example.compute bundle(下文简称compute bundle)提供了统一的计算接口:Compute,另外两个bundle分别为osgi.example.compute.add(下文简称add bundle)osgi.example.compute.multiply(下文简称multiply bundle),在这两个bundle中,各自对compute bundle进行不同的实现,一个实现加法,一个实现乘法。另外还有一个服务消费者osgi.example.compute.consumer bundle(下文简称consumer bundle)consumer bundle负责消费add bundlemultiply bundle提供的服务。上述4bundle之间的关系如下图所示:

 

 

         创建4bundle之后的工程目录如下图所示:

 

通过该示例,将讲解如下内容:

 

l  bundle之间如何实现包依赖

l  bundle如何将服务注册到Equinox运行环境

l  bundle如何调用其他bundle已注册的服务

1.  导出包

首先,我们来看看compute bundle,它只对外公布Compute接口,除此之外,bundle不包含其他内容,因此在它的MANIFEST.MF文件中,只需声明Export-Package即可,如下所示:

Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: Compute Plug-in
Bundle-SymbolicName: osgi.example.compute
Bundle-Version: 1.0.0
Bundle-ActivationPolicy: lazy
Bundle-RequiredExecutionEnvironment: J2SE-1.5
Import-Package: org.osgi.framework;version="1.3.0"
Export-Package: osgi.example.compute

 

2.  引入包

add bundlemultiply bundle需要实现compute bundle的公布的Compute接口,同时又要将自身的AddMultiply类公布给其他bundle,所以需要声明ExportImport两项内容,如下所示——multiply bundleMANIFEST.MFadd bundle相似:

 

 

提示:MANIFEST.MF文件中有个细节需要注意,所有的头部,如Import-Package,都必须顶头写,如果该头部信息较长,需要换行,则换行需要空至少一格,否则会报错。

 

 

 

这样,我们将osgi.example.compute包引入add bundle中,可以像本地接口一样使用Compute接口了,如果足够细心的话,你将发现add bundle的工程目录结构发生了一个小小的变化,如下图所示:

 


 osgi.example.compute工程被添加至当前工程的插件依赖环境中。

 

public void start(BundleContext context) throws Exception {
	context.registerService(Add.class.getName(), new Add(), null);
}

 

Equinox提供了两种服务注册方式:

l  registerService(String,Object,Dictionary) 注册服务对象 object 到服务名 String 下,可以携带一个属性字典 Dictionary

l  registerService(String[],Object,Dictionary) 注册服务对象 object 到服务名数组 String[] 下,可以携带一个属性字典 Dictionary,即一个服务对象可以按照多个接口名字注册,因为类可以实现多个接口;

 

4.   消费服务

相应的,如何消费add bundle注册的服务呢?让我们看看consume bundle中的Activator类的start方法:

ServiceReference addReference = context.getServiceReference(Add.class.getName());
Compute compute = (Compute)context.getService(addReference);
System.out.println(compute.compute(5, 6));

ServiceReference multiplyReference = context.getServiceReference(Multiply.class.getName());
compute = (Compute)context.getService(multiplyReference);
System.out.println(compute.compute(5, 6));

 

 

 

首先我们看到的是getServiceReference方法,通过该方法可以查询已注册的服务,Equinox提供两种查询方式:

l  getServiceReference(String):根据服务的名字得到服务的引用;

l  getServiceReferences(String,String):根据服务名和另外一个过滤器名字对应的过滤器得到服务的引用;

之后,根据查询到的服务,从bundle context中获取相应的服务,即可完成服务调用。

 

5.   运行bundle

根据helloworld讲到的运行方式,将computeaddmultiplyconsumer4bundle装载到Equinox中,运行结果如下:

osgi> 11

30

 

键入命令ss ,可以看到各个bundle的状态:

Framework is launched.

 

id  State       Bundle

0   ACTIVE      org.eclipse.osgi_3.4.3.R34x_v20081215-1030

1   ACTIVE      osgi.example.compute.multiply_1.0.0

2   ACTIVE      osgi.example.compute.consumer_1.0.0

3   ACTIVE      osgi.example.compute_1.0.0

4   ACTIVE      osgi.example.compute.add_1.0.0

 

运行成功!

 

 

总结:通过阅读本文,初步掌握了如何利用Equinox开发OSGi应用,了解了bundle之间是如何进行包依赖的,如何注册、查询及消费服务的。

利用OSGi框架,我们可以很好实现软件的模块化开发,这一点有别于传统的模块化的概念,传统的模块化开发方式,只是从代码组织上进行模块化划分,而并未做到ClassLoader的隔离,模块与模块之间仍然可以通过Classpath完全暴露,而OSGi的各个bundle都拥有自己的ClassLoader环境,如果bundle内部的包未被导出,那么对于外界是不可见的。加之OSGi支持热部署,并且具备版本识别能力,即相同IDbundle可以同时部署不同的版本,这样并不会引起冲突,这将极大的推动动态模块化开发的进程。

读完本文之后,我相信大家应该能够体会到OSGi所带来的好处,可是有一个很大的问题,因为OSGi在客户应用领域仍处于起步阶段,一些常用的第三方开源Jar包原本并不符合OSGibundle规范,还需要进行大量的改造工作,这也就是上文所说的OSGi的生态环境还不健全,比如我们平常所用的strutsjdbc驱动、数据库连接池、log4j等等,不过,我相信在不久的将来,这些问题都会解决的,我想那个时候真正的OSGi时代也就真的到来了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值