基于OSGi的声明式服务
1. 引言
OSGi(Open Services Gateway Initiative)有双重定义。一方面它指OSGi Alliance组织;另一方面指该组织制定的一个基于Java语言的服务规范——OSGi服务平台。OSGi Alliance是一个由Sun Microsystems、IBM、爱立信等于1999年3月成立的开放的标准化组织。该组织及其标准原本目的在于使服务提供商通过住宅网关为各种家庭智能设备提供各种服务,目前该平台逐渐成为一个为室内、交通工具、移动电话和其他环境下的所有类型的网络设备的应用程序和服务进行传递和远程管理的开放式服务平台。
该规范和核心部分是一个开放并提供统一接口标准的体系框架,其中定义了应用程序的生命周期模式和服务注册,基于这个体系机构,服务提供商、程序开发人员、软件提供商、服务网管运营商、设备提供商能够协调地联合起来开发,部署以及管理向用户提供的各种服务。这个框架实现了一个优雅、完整和动态的组件模型。应用程序(称为bundle)无需重新引导可以被远程安装、启动、升级和卸载(其中Java包/类的管理被详细定义)。API中还定义了运行远程下载管理政策的生命周期管理。服务注册允许bundles去检测新服务和取消的服务,然后相应配合。
2. 声明式服务出现及其组成
OSGi框架包含一套编程式的服务模型,它提供了服务的发布、查找和绑定操作。这个模型是简单而且强大的,它使应用能通过服务方式同外部的bundle进行通讯和协作。在OSGi服务层定义了一个和生命周期层紧密结合的动态协作模型,一个服务(service)就是一个通过服务登记来注册到一个或者多个Java接口下的Java对象。
当OSGi的服务模型应用于大型的系统和大范围的部署会带来一些兼容性问题,例如:
Ø 启动时间----编程式的服务模型需要bundle主动地注册服务和获取服务,这些工作通常在启动时执行,需要bundle在其激活器中执行初始化。在一个大型系统中,它会延长系统的启动时间,不能快速的响应结果。
Ø 内存占用----一个服务被注册到框架中意味着服务实现相关的类和对象被装载到内存中,如果服务从不被使用的话,那么这个内存是没有必要被占用的,而且创建一个类加载器可能引起显著的开销。
Ø 复杂性----服务能够在任何时候注册和注销。这种动态的特性使得编程式的服务模型比传统的方式更加复杂,这些复杂性对开发健壮的和可靠的应用会起到消极的作用,因为这些应用不能保证所有的动态处理总是正确。
针对编程是服务模型存在的上述问题,我们提出了新的服务构件模型Declarative service声明式服务的方式来发布、查找和绑定OSGi的服务。
声明式服务中引入了两个元素,构件(component)和元数据文件(metadata.xml)。构件是一个物理的、可替换的系统组成部分,它包装了实现体且提供了对一组服务接口的实现方法。构件自身必须相容于接口且实现接口,接口表示了驻留在构件内的成分所实现的服务。这些服务定义了的一个整合的行为,并从一些构件实例提供给其它客户端构件实例。在声明式服务中一个构件就对应了某一个构件实现类,这个类相当于是一个pojo(普通的Java对象),在这个类中我们可以注册服务、引用服务、构件属性配置等一些满足特定需求的操作,总之构件是服务的提供者和使用者。而元数据文件则是一个xml文件,在声明式服务中所有的元数据文件名称都为metadata.xml,在这个xml文件中我们可以根据需求配置构件的一些必需信息,且所配置的这些信息必须遵循声明式服务元数据规范。
声明式服务主要由四个部分组成,声明式服务容器部分、元数据解析部分、代码织入部分和打包成声明式服务bundle的插件部分。
Ø 声明式服务容器----用来解析部署到OSGi环境中的bundle,存放所有已创建的服务构件实例和方面构件实例,并对其相应的配置信息、生命周期进行管理。
Ø 元数据解析----用来解析bundle中的元数据文件信息,使用SAX解析器将元数据文件中每一个节点的信息都解析出来,构造成构件(component)或是构件实例(instance)供声明式服务容器使用。
Ø 代码织入----针对构件实现类进行的操作,主要是在构件实现类已实现的服务接口中增加一个pojo接口(用来获取当前服务对象的构件实例,给某个字段注入值),并在相应的构件实现类基础上生成以"_WC_ "开头的字节码文件。
Ø 声明式服务插件----将构件所在工程打包成声明式服务的bundle,在打包的过程中对构件实现类进行织入、对元数据文件进行解析并增强并在该bundle的manifest文件中添加与声明式相关的头标信息。
图1是组成声明式服务的模块图,其中Loong Dservice Impl是声明式服务容器部分,Loong Dservice Metadata是元数据解析部分,Loong Dservice weaver是代码织入部分,Loong Dservice plugin是声明式服务插件部分。
图1 声明式服务模块图
3. 声明式服务的优点
声明式服务是一个基于OSGi框架面向服务的构件模型,采用服务组件的延迟加载以及组件生命周期管理的方式来控制对于内存的占用以及快速启动。
这种方式简化了OSGi服务的开发者执行服务注册和处理服务依赖的工作,从而可以使编程的工作减少到最小;它也允许服务构件在需要时才进行加载。作为这种方式的结果,bundle中不再需要提供BundleActivator来通过服务注册库与其它的bundle进行协作。
从系统的角度来看,服务构件模型意味着减少了启动时间和潜在的降低了内存的占用。从一个程序员的角度来看,服务构件模型提供了一种简化的编程模型。
DService声明式服务框架是提供了一个简单的、可扩展的、基于POJO的面向服务构件开发模型;是基于OSGi扩展规范中的Declarative ServicesSpecification的参考实现。它提供声明元数据的方式开发OSGi环境中的服务构件,由框架管理构件实例,从而简化了因管理动态环境而导致的非功能性需求;它可以通过集成功能性或非功能性方面构件快速开发出一个业务构件。非侵入式编程,开发人员只需要关心自己的业务逻辑。
总之,声明式服务有以下几方面的特性:
Ø 简化开发方式:开发一个应用无需关注OSGi或DService相关的API,也无需控制构件组装与它们的生命周期,只需要开发若干POJO和相应的xml元数据。
Ø 服务的动态性管理:Dservice框架与OSGi框架相结合,任何关于服务的管理都由DService框架来完成,包括发布服务、引用服务、受管服务等等。
Ø 服务对象依赖注入:框架可以为构件实例管理所有的服务依赖。
Ø 构件延迟实例化:构件实例可以等到需要它时才被创建,这样可以避免启动占用太多的时间和空间。
Ø 可扩展:Dservice框架的高可扩展性可以让开发人员自己为框架动态的增加其自定义的功能(比如提供一个远程的OSGi服务、使用JMX等)。
Ø 编译期代码织入:生成子类继承用于开发的构件实现类,保持用户代码纯洁、可调试。
上一篇: OSGI心得体会
推荐阅读