介绍了组件开发与Bndtools。
在本教程中,我们将建立两个组件和API组成的一个示例应用程序。?下图显示了包的体系结构(简化):
在本教程中,我们创建了前三名束(矩形):
monospace; font-weight: bold; color: #bb260d;">Greeting
?。Command
所使用的菲利克斯壳牌捆绑服务。请参阅安装说明?。
首先,我们需要创建一个Bndtools OSGi的项目。?这仅仅是一个标准的Eclipse Java项目,一个额外的建设者构建OSGi包。
从文件菜单,选择新建- > Bndtools OSGi的项目?。
在接下来的页面中,输入org.example.api
作为项目的名称。?至少选择J2SE-1.5的JRE的执行环境。
接下来,您提供的项目模板的选择,开始您的项目。?选择空项目?,然后单击Finish。?新项目将被创建。
如果这是您第一次在此工作区中使用Bndtools,你现在会看到“欢迎”对话框。?单击下一步后完成以允许Bndtools设置一个配置项目并导入基本信息库。?库是哪里,你在你的项目中使用包存储在一个地方。?远程“BndTools枢纽”资源库在默认情况下,它包含了一些经常使用的包创建的。
要点:
cnf
即通常开发人员之间共享包含项目工作区范围内的配置。?它可能还包含包的存储库。
bnd.bnd
在每个Bndtools项目,控制项目的设置的顶部创建的。?相同的设置所使用的BND当它从离线ANT构建调用。
的OSGi提供的功能,生产者和消费者的强脱钩。?这是通过鼓励基于API的(或者在Java方面,基于接口)编程模型,其中生产者功能实现的API和功能绑定的消费者只的API,没有任何特定的实现完成。对于我们的例子中,我们将使用一个相当简单的API。
在src
新项目的目录中,创建一个名为包org.example.api
?。?在新的包中创建一个名为Java接口Greeting
?,如下所示:
package org.example.api; public interface Greeting { String sayHello(String name); }
我们已经创建的项目定义了一个捆绑符号名称(BSN)单束org.example.api
?(即,相同的项目名称)。?当我们创建的项目,名为包文件org.example.api.jar
在创建generated
目录,它会在每次我们改变了束定义或它的源代码的时间重建。
然而,捆绑目前是空的,因为我们还没有定义任何Java包的捆绑,包括。?这是Bndtools相对于其他工具的一个重要的区别:束总是空的,直到我们显式地添加一些内容。?您可以通过双击该包文件并查看其内容验证这一点:它只会有一个META-INF/MANIFEST.MF
条目。
我们希望将包添加org.example.api
到该包的导出包。?于是打开bnd.bnd
在项目的顶层文件,并选择目录选项卡。?现在,该软件包可以通过以下两种方式之一来补充:
org.example.api
从对话框,然后单击OK(确定)或?...org.example.api
从Eclipse的Package Explorer视图进入导出软件包列表中。(提示:高级用户可能更愿意进入Export-Package: org.example.api
手动在Source选项卡)。
只要做到这一点,出现标题为“缺少包装信息”弹出对话框。?此对话涉及到包的版本:它要求我们声明此导出的软件包的版本。?单击OK(确定)。
目录选项卡现在应该会出现在下面的截图:
保存文件,并捆绑将被重建以包括选定出口。?我们可以通过打开导入/导出视图,并选择在Package Explorer中的包文件确认。?请注意该包已被分配1.0.0版本:
要点:
bnd.bnd
?。META-INF/MANIFEST.MF
?。
现在,我们将创建另一个项目,定义了两个包:在一个供应商和客户Greeting
的API。
创建另一个Bndtools项目,命名为org.example.impls
?。?在项目模板步骤中,选择组件开发(声明式服务),然后单击Finish。
我们需要的API项目添加为这个新项目的生成时间依赖性。
该bnd.bnd
新创建的项目的文件都会自动打开。?单击Build选项卡并添加org.example.api
通过以下任一方式:
单击?Build?路径面板工具栏中的“+”图标。?双击org.example.api
下,在出现的对话框中“工作区”;它会在移动到右侧。?单击Finish(完成)
或拖动和拖放org.example.api
从库查看到构建路径面板。
在这两种情况下,?org.example.api
束将出现在构建路径面板的版本注释“最新的”:
保存该文件。
要点:
bnd.bnd
编辑器。我们将编写一个实现类Greeting
接口。?当项目从模板创建,Java源代码名为类org.example.ExampleComponent
生成。?现在打开这个源文件,并使其实现Greeting
?:
package org.example; import org.example.api.Greeting; import aQute.bnd.annotation.component.Component; @Component public class ExampleComponent implements Greeting { public String sayHello(String name) { return "Hello " + name; } }
注意使用的@Component
注解。?这使得我们的捆绑使用OSGi的声明式服务来声明API的实现类。?这意味着类的实例将被自动创建,并与OSGi服务注册表中注册。?注释是编译时只,而不会污染我们的类的运行时依赖关系 - 换句话说,这是一个“普通Java对象”或者是POJO。
我们应该编写一个测试案例,以确保按预期实现类作品。?在test
文件夹,一个测试用例类已经存在一个名为org.example.ExampleComponentTest
?。?写一个测试方法如下:
package org.example; import junit.framework.TestCase; public class ExampleComponentTest extends TestCase { public void testSaysHello() throws Exception { String result = new ExampleComponent().sayHello("Bob"); assertEquals("Hello Bob", result); } }
现在,在文件上单击鼠标右键并选择?Run?As> JUnit的测试?。
验证JUnit视图显示一个绿色的吧。?如果没有,回去和修复代码!
需要注意的是,由于这是一个单元测试,而不是一个集成测试,我们并不需要运行一个OSGi框架;?该标准的JUnit启动器使用。?再次,这是可能的,因为所检测的部件是一个POJO。
正如在以前的项目,一个包会自动根据内容内置bnd.bnd
?。?在当前项目中但是,我们要建立两个独立的包。?为了实现这一目标,我们需要启用一个名为“子束”功能。
在项目上单击右键org.example.impls
并选择New>包描述符?。?在出现的对话框中,键入名称provider
?,然后单击Finish。
一个弹出对话框询问是否要启用子束。?单击OK(确定)。
有些设置会从移动bnd.bnd
到新provider.bnd
文件。?现在你应该找一个包中generated
一个名为org.example.impls.provider.jar
其中包含org.example
封装和声明式服务组件声明OSGI-INF/org.example.ExampleComponent.xml
?。
要点:
bnd.bnd
?。.bnd
文件。?该bnd.bnd
文件仍用于定义项目范围的设置,如构建依赖关系。
现在我们想运行OSGi的。?为了实现这一目标,我们需要创建一个“运行描述符”,它定义捆绑运行的集合,连同其他一些运行时设置。
在项目上单击右键org.example.impls
并选择New>运行描述?。?在出现的对话框中,输入run
作为文件名 ??,然后单击下一步?。?在对话框的下一个页面会要求我们选择一个模板;?选择阿帕奇菲利克斯4勾勾外壳?,然后单击Finish。
在编辑器中的新run.bndrun
文件,点击运行OSGi的靠近右上角。?不久,菲利克斯Shell提示符“?g!
?“将出现在控制台视图。?键入lb
命令来查看包的列表:
g! lb START LEVEL 1 ID|State |Level|Name 0|Active | 0|System Bundle (4.0.3) 1|Active | 1|Apache Felix Gogo Runtime (0.10.0) 2|Active | 1|Apache Felix Gogo Shell (0.10.0) 3|Active | 1|Apache Felix Gogo Command (0.12.0) g!
下一步,我们希望包括org.example.impls.provider
和osgi.cmpn
束。?这可完成如下:
org.example.impls.provider
?。osgi.cmpn
?。运行要求面板现在看起来应该像这样:
检查保存自动解析?,然后保存该文件。?返回到控制台视图,类型lb
再次:
g! lb START LEVEL 1 ID|State |Level|Name 0|Active | 0|System Bundle (4.0.3) 1|Active | 1|Apache Felix Gogo Runtime (0.10.0) 2|Active | 1|Apache Felix Gogo Shell (0.10.0) 3|Active | 1|Apache Felix Gogo Command (0.12.0) 4|Active | 1|Apache Felix Configuration Admin Service (1.4.0) 5|Active | 1|Apache Felix Log Service (1.0.1) 6|Active | 1|Apache Felix Declarative Services (1.6.2) 7|Active | 1|org.example.api (0.0.0) 8|Active | 1|org.example.impls.provider (0.0.0) 9|Active | 1|osgi.cmpn (4.2.0.200908310645) g!
该供应商捆绑已被添加到运行时动态。?请注意,该API包和Apache菲利克斯声明式服务也将被添加,因为它们解析为供应商的依赖。
现在我们可以看看使用命令由我们提供捆绑发布的服务inspect capability service 8
?:
g! inspect capability service 8 org.example.impls.provider [8] provides: ---------------------------------------- service; org.example.api.Greeting with properties: component.id = 0 component.name = org.example.ExampleComponent service.id = 24 g!
我们现在捆绑下的出版服务Greeting
界面。
要点:
.bndrun
文件。?多个不同的运行配置可以被使用,从而导致不??同的集束,不同的OSGi框架的实现等
bndrun
文件会导致包的列表中进行动态更新。?因此,我们可以在不重新启动添加和删除软件包。
最后,我们将编写消耗问候服务,并公布可从菲利克斯shell调用shell命令的组件。
首先,我们需要做的菲利克斯外壳API可用来编译反对。?打开bnd.bnd
并变更为Build选项卡。?添加org.apache.felix.gogo.runtime
的编译依赖列表,并保存文件:
现在,在其下创建一个新的Java包src
文件夹名为org.example.command
?。?在这个包中创建一个类GreetingCommand
如下:
package org.example.command; import org.apache.felix.service.command.CommandProcessor; import org.example.api.Greeting; import aQute.bnd.annotation.component.Component; import aQute.bnd.annotation.component.Reference; @Component(properties = { /* Felix GoGo Shell Commands */ CommandProcessor.COMMAND_SCOPE + ":String=example", CommandProcessor.COMMAND_FUNCTION + ":String=greet" }, provide = Object.class ) public class GreetingCommand { private Greeting greetingSvc; @Reference public void setGreeting(Greeting greetingSvc) { this.greetingSvc = greetingSvc; } public void greet(String name) { System.out.println(greetingSvc.sayHello(name)); } }
该命令组件是不提供包的一部分,因为它生活在那个没有包含一个包。?我们可以将其添加到供应商捆绑,但它会更有意义创建一个单独的包吧。
再次右键单击在org.example.impls
项目,然后再次选择New>包描述符?。?输入名称为command
?,然后单击Finish。
添加包org.example.command
到新创建的文件的私人包面板。?和以前一样,这样可以使用“+”按钮,在工具栏或通过拖放式操作来完成。
我们还需要声明该软件包包含声明式服务组件。?切换到编辑器的内容选项卡,并在声明式服务下拉列表中选择Bnd注解?。?现在保存文件。
切换回编辑run.bndrun
?。?在运行要求选项卡,添加org.example.impls.command
捆绑,并保存文件。
该命令包现在打字的时候出现在包列表lb
?:
g! lb START LEVEL 1 ID|State |Level|Name 0|Active | 0|System Bundle (4.0.3) 1|Active | 1|Apache Felix Gogo Runtime (0.10.0) 2|Active | 1|Apache Felix Gogo Shell (0.10.0) 3|Active | 1|Apache Felix Gogo Command (0.12.0) 4|Active | 1|Apache Felix Configuration Admin Service (1.4.0) 5|Active | 1|Apache Felix Log Service (1.0.1) 6|Active | 1|Apache Felix Declarative Services (1.6.2) 7|Active | 1|org.example.api (0.0.0) 8|Active | 1|org.example.impls.provider (0.0.0) 9|Active | 1|osgi.cmpn (4.2.0.200908310645) 10|Active | 1|org.example.impls.command (0.0.0) g!
最后,?greet
命令现在将可从勾勾外壳:
g! greet BndTools Hello BndTools g!