OSGi enRoute – 2.2_3 – API工程

你将会在本节中学到什么

在本节中我们将会为一个简单的表达式计算器创建一个API。本节中将会告诉你如何创建一个API工程,如何命名一个工程,并且如何在工程中导航。

你应该已经根据前面的章节内容设置了一个空的工作空间。本文假定你已经在bndtools视图中了。

本节对API工程进行了讨论。一个API工程可以被用在classpath之上但是不能在框架内部运行。一般来说API包会被一个Provider bundle包含。

创建一个工程

我们准备创建一个用于计算表达式的组件。尽管我们可以直接实现它,但还是使用正确的方式先定义契约。服务契约现在可以是一个接口:

OK,没有比这更简单的事情了!

在各自的工程中给出服务契约,以便于分享它们,这是最佳实践之一。下面来创建一个API工程。OSGi enRoute为API工程设置了特殊模板。当新的工程名称以.api结尾时,它会假定该工程为API工程。

enRoute能识别的名称并不仅仅只有API工程。你还可以使用如下后缀:

● .test – 一个OSGi测试工程,测试会在框架内部运行。

● .provider, adapter –一个实现工程

● .api – API工程

● .application – 一个应用程序工程。它将一些组件绑定到一起并参数化它们。

模板中的一个bug导致名称至少由3部分组成,类似:a.b.api。

因此让我们通过菜单 New/Bndtools/Bnd OSGi Project来创建 com.acme.prime.eval.api 工程。

这将会打开一个对话框页面,我们从中可以选择一个模板。在模板中,选择OSGi enRoute模板。OSGi enRoute模板将会根据你的工程名的最后一部分或扩展名来选择一个合适的布局。

20171015_2_001

为工程添加名称 (com.acme.prime.eval.api)。

20171015_2_002

然后你可以点击Next按钮。在这个页面上我们并不需要设置任何参数,只需要继续点击Finish按钮。这将会创建一个很小的工程,它会带有所有API工程所需的各类选项。模板已经在正确的包中为你创建了Eval接口,根据我们之前讨论的内容完善对应的代码。

20171015_2_003

这样你已经顺利创建了第一个Bundle!如果你不相信,则可以进入工程中的generated文件夹并双击 com.acme.prime.eval.api.jar文件。这将会在刚创建的Bundle上打开一个JAR Viewer。默认情况下,它将会打开由bnd生成的Manifest文件,你还可以浏览Bundle内的其它内容。

20171015_2_004

导出

注意,在Manifest中我们已经导出了com.acme.prime.eval.api包。导出意味着它可以被其它Bundle所访问。你可以通过双击bnd.bnd文件并选择Contents选项卡来查看导出(和导入)的内容。在Export Packages列表中,你可以看到我们在此包中导出的内容。

20171015_2_005

我们的API Bundle现在看起来如下所示:

20171015_2_006

在图中圆角矩形框表示一个Bundle;内部的黑框表示导出的包。

版本控制

你可能没有注意到,但实际上你已经语义化地对此包进行了版本化(你喜欢魔法吗?)在com.acme.prime.eval.api 包中,你可以看到package-info.java文件。双击将会显示其中的内容。在这个文件中,我们将定义包的版本。如果你修改了包的内容,你应该同时保持更新这个文件中的版本。

Provider 以及 Consumer 类型

在这个API中,任何实现Eval接口的内容都可以被视作Provider。与API的Consumer不同,一个Provider必须完全实现一个几乎没有向后兼容性的契约,版本的任何会影响公开API的变化都会导致对Provider的Bundle的重新构建。也就是说,如果我们的版本是1.1,我们希望确保实现了1.0的Provider不再兼容它。

显然,确保合适的版本范围被使用是一个噩梦。我们可以通过在接口上添加注解来协助Provider解决这个问题:

bnd工具将会自动保证此接口的实现使用语义化版本管理机制来导入指定范围的包,例如[1.0,1.1)。被API的Consumer所实现的接口(通常类似listener接口)可以使用 @ConsumerType注解,这是默认的行为。

如果你觉得这个理解起来有点困难是正常的,这是一个非常复杂的话题。我们将会在后面重新回顾这个问题。

Compile Only

如果你查看bnd.bnd文件,你会看到此API Bundle是compile only的:

 

它是compile only的原因在于Provider应该导出其API是一个最佳实践。关于这个话题已经有了无数的讨论并且有一些不同的意见。然而,一个API的Provider与其提供的API的版本是紧密相关的。API的改变需要Provider也进行改变,与API Consumer一样,它们没有向后兼容性。因此,从Provider中导出API会使得整个系统降低复杂度。

它是如何工作的?

一个bnd工程时被bnd.bnd文件控制的。这个属性文件定义了版本、构建路径以及哪个包应该放到Bundle之中。在本例中,该文件如下所示:

Bndtools会根据这些信息指示Eclipse进行相应的动作。在我们后续会讲到的Gradle构建环境中,bnd会指示Gradle环境进行相应动作,因此两种环境都能够构建相同的JAR包。

打赏一下
支付宝
微信
除非注明,博客文章均为原创,转载请标明文章地址
本文地址: http://www.javafxchina.net/blog/2017/10/osgi-enroute-0202-03/
百度已收录