OSGI传统注册式服务与声明式服务
Posted 叶长风
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了OSGI传统注册式服务与声明式服务相关的知识,希望对你有一定的参考价值。
上一篇博文中我们编写了第二个简单的osgi的example,并编写了一个接口DictionaryService,并在Activator这个Bundle中实现了这个interface,并在start启动方法中进行了osgi服务的注册,但并没有使用这个服务,这一篇文章中并不讲解怎么使用这个已经注册的服务,但是会讲解服务的使用方式,一种为声明式服务,一种为传统注册式服务,以下就是开始讲解何为osgi的注册式服务与声明式服务。
传统注册式服务
传统方式下,我们注册服务都是在bundle的激活器(Activator)中使用BundleContext.registerService()方法完成的。而服务的获取需要通过BundleContext.getServiceReference()获取ServiceReference实例,进而使用BundleContext.getService()得到真正的服务实例。这种方式虽然能够完成服务的发布与使用,但是带来一定的问题,具体如下:
产生较多的样板式代码。OSGi的bundle是动态化的,伴随着bundle的安装和卸载,它所发布的服务也会动态地处于可用或不可用的状态,因此每次使用服务的时候,我们都需要借助BundleContext对象去服务注册中心查找,而不能通过一次查找,一劳永逸地持有服务对象的引用。尽管有ServiceListener和ServiceTracker帮助我们监听和跟踪服务的状态,但是总体而言这种方式较为繁琐且容易出错。
影响启动时间,服务在激活器中注册时,需要实例化所有要发布的服务对象,因为激活器的start()方法是同步调用的,所以会影响到整个应用的启动时间。
加大内存的占用,在激活器中注册服务时,我们需要实例化所有的服务对象,但是这些服务在应用运行期间,并不一定会用到,这在无形中加大了内存的占用。
API依赖引起的平台侵入性。使用传统方式注册和使用服务,会用到大量的OSGi API,从而产生与OSGi平台的耦合,如果要将代码复用到非OSGi场景之中,需要较多的重构工作。
传统的注册式的服务写起来繁琐,并且问题比较多,因此一般都是使用声明式服务来替代,以下就开始讲解声明式服务。
声明式服务
osgi是通过声明式服务来解决以上存在的问题的,声明式服务中引入了两个元素,构件(component)和元数据文件(metadata.xml)。构件是一个物理的、可替换的系统组成部分,它包装了实现体且提供了对一组服务接口的实现方法。构件自身必须相容于接口且实现接口,接口表示了驻留在构件内的成分所实现的服务。这些服务定义了的一个整合的行为,并从一些构件实例提供给其它客户端构件实例。在声明式服务中一个构件就对应了某一个构件实现类,这个类相当于是一个pojo(普通的Java对象),在这个类中我们可以注册服务、引用服务、构件属性配置等一些满足特定需求的操作,总之构件是服务的提供者和使用者。而元数据文件则是一个xml文件,在声明式服务中所有的元数据文件名称都为metadata.xml,在这个xml文件中我们可以根据需求配置构件的一些必需信息,且所配置的这些信息必须遵循声明式服务元数据规范。
声明式服务主要由四个部分组成,声明式服务容器部分、元数据解析部分、代码织入部分和打包成声明式服务bundle的插件部分。
- 声明式服务容器—-用来解析部署到OSGi环境中的bundle,存放所有已创建的服务构件实例和方面构件实例,并对其相应的配置信息、生命周期进行管理。
- 元数据解析—-用来解析bundle中的元数据文件信息,使用SAX解析器将元数据文件中每一个节点的信息都解析出来,构造成构件(component)或是构件实例(instance)供声明式服务容器使用。
- 代码织入—-针对构件实现类进行的操作,主要是在构件实现类已实现的服务接口中增加一个pojo接口(用来获取当前服务对象的构件实例,给某个字段注入值),并在相应的构件实现类基础上生成以”WC “开头的字节码文件。
-声明式服务插件—-将构件所在工程打包成声明式服务的bundle,在打包的过程中对构件实现类进行织入、对元数据文件进行解析并增强并在该bundle的manifest文件中添加与声明式相关的头标信息。
总结
这篇文章讲解了传统的注册式服务和声明式服务,注册式服务在前面一篇的博文中有所提及,在后文中还是有相应的使用,但在声明式服务上,后文中将会使用blueprint来代替,Blueprint规范来源于Spring Dynamic Modules项目,最早出现于R4.2企业规范之中。这个到了日后讲解blueprint的时候再具体讲解这些。
以上是关于OSGI传统注册式服务与声明式服务的主要内容,如果未能解决你的问题,请参考以下文章
使用 Guice/Peaberry 进行 osgi 声明式服务
使用 osgi 的声明式服务时,我可以在同一个组件中提供和引用服务吗?