在近日举办的EclipseCon 2011上,下一版的核心OSGi平台发布了最终草案,其文档将于不久之后发布。BJ Hargrave在演讲中介绍了OSGi 4.3的新特性,并且概述了它与旧版之间的差别。
泛型
意料之中的一个特性就是核心OSGi API增加了泛型支持。这样就可以通过类型安全的操作查找特定类型的服务了,从而不必进行类型转换。然而,由于OSGi需要运行在嵌入式(1.5之前)VM上,因此没法使用1.5的编译器来构建核心API。但很多人都会忽略-target jsr14这个选项,我们可以使用它编译使用了泛型的Java代码并运行在1.4兼容的JRE上。引入该选项的初衷是向JSR 14中的泛型进行迁移,但现在很多编译器都将其保留了下来。这样客户端代码(使用了-target jsr14选项在1.4下编译,或是在1.5+上编译)就可以引用服务了,如下代码所示:
// OSGi 4.2 way // ServiceReference ref = context.getServiceReference( // LogService.class.getName()); // LogService log = (LogService)context.getService(ref); // OSGi 4.3 way ServiceReference<LogService> ref = context.getServiceReference( LogService.class); LogService log = context.getService(ref);
然而,由于核心并非完全兼容于1.5,因此并没有使用其他特性(诸如枚举和注解)。
Capabilities
在OSGi环境中,传统的依赖单元要么是package依赖,要么是bundle依赖(通过Import-Package或是Require-Bundle)。虽然这些依赖对于代码没什么问题,但他们却没法很好地表达非代码的依赖。比如说,某个bundle可能需要一些内存或是Web服务器,但这两者都没法通过具体的package或是bundle来表示。
OSGi 4.3引入了通用capability的概念,它可与Require-Capability和Provide-Capability搭配使用。在解析bundle之前必须得满足必要的capability需求。其典型使用场景是用于提供OSGi的声明式服务,该服务并不会表示为package依赖,但为了能够正确解析bundle,我们还是需要它的。
此外,所需的最小版本号可以通过capability的形式展现出来:
// Old way // Bundle-RequiredExecutionEnvironment: JavaSE-1.6 // New way Require-Capability: osgi.ee;filter:="(&(osgi.ee="JavaSE")(version>=1.6))"
出于通用性的考量,OSGi 4.3已经不建议使用Bundle-RequiredExecutionEnvironment了(但仍然存在)。
Remote Services
OSGi Remote Services并非新特性(OSGi 4.2纲要的第13章已经对其进行了介绍),但他们已经被加到了OSGi 4.3 Core规范当中了。这样,所有的OSGi 4.3运行时都将会支持Remote Services。
适配
某些服务(如PackageAdmin)用于提供关于bundle的元信息,同时又不会使用特定类型的访问符污染bundle的接口。这样我们通常都会使用一些样板代码来确定bundle是如何连接的,或是其起始层次是什么。
简化很重要,OSGi 4.3为Bundle引入了一个adapt(类)方法。类似于Eclipse的IAdaptable平台,Bundle可以转换为已知类型。本质上,如果bundle知道如何将自身转换为给定类型,那它就会返回一个实例;如果不知道(或是没有权限),那么就会返回null。这简化了PackageAdmin和StatLevelAdmin,如下代码所示:
BundleWiring wiring = bundle.adapt(BundleWiring.class); // wiring.getRequirements(null) BundleStartLevel bsl = bundle.adapt(BundleStartLevel.class); // bsl.getStartLevel()
现有的服务依然可用,但推荐普通用户使用新的adapt模式以简化实现。
Weaving
Weaving支持也得以实现,这样扩展就可以插入到其他bundle的类加载机制中了。某些运行时系统使用了该技术,尤其是那些实现了JPA或是数据库持久化存储的系统——为了创建特定于该类型的代码。凭借Weaving回调,我们可以将标准的机制插入到OSGi框架中,而之前使用的则是特定于提供商的机制。
嵌套框架遭抛弃
虽然Equinox中已经有了一个试用的实现,但嵌套框架支持(意即框架可以加载嵌套的版本)却被4.3规范所抛弃了。
但却引入了更加强大的BundleHook和ResolverHook API,这样扩展就可以创建虚拟的bundle集合,使之相互不可见。这种想法来源于之前的ServiceHook,它可以实现服务之间的隐藏。
这样就可以通过创建彼此不可见的bundle分组来模拟嵌套框架了。它已经用于实现新的Virgo region model,后者则重新实现以支持这种新模型。
其副作用是如果彼此不可见,那么它可能会在同一个框架中安装相同bundle/version的多个版本。此前,当尝试再次安装相同的bundle时会出现错误。默认情况下这是不行的,但却可以在加载框架时在属性文件中通过org.osgi.framework.bsnversion=multiple属性实现这一点。默认情况下,该属性是org.osgi.framework.bsnversion=single。
总结
新的OSGi规范会为框架引入大量有用的特性;对于那些不需要支持老框架的bundle来说,新的泛型API极具吸引力,可以促成他们的转换。嵌套框架与weaving不太可能产生直接的效果,但那些实现底层库的bundle则会通过标准的回调转换到这上面来,这会增加不同的OSGi框架之间的平台交互性。
该规范尚未正式发布,但预计会在今年Eclipse发布前发布,因为Equinox 3.7很可能会成为参考实现。