因为JES使用组件模型,在这个模型里,组件一个挨一个地插入框架,所以如果某个包导出了服务,其它的包就可以利用这个包的服务。一个包的服务,也可以由另一个更完善的服务利用,从而得到更丰富的功能。
假设我们有这样一个包,它负责为俱乐部招收新成员。在这个过程里,我们要利用随意问候实现GreetingService 向新成员表示问候。
在这个例子里,俱乐部包club 依赖问候服务GreetingService。这个例子没有显示俱乐部包club的服务,它只通过使用服务引用ServiceReference对象,显示我包含问候服务GreetingService的激活器类Activator。
服务引用对象ServiceReference 指的是对服务的引用。如果一个包要利用其它的服务,它必须要取得一个服务引用ServiceReference 对象,然后用服务引用对象ServiceReference获取服务。因为首先得到的是服务引用对象ServiceReference,所以在使用它之前,可以检查服务的属性。一个在框架中登记了的服务,可能会有多个不同的服务引用对象ServiceReference 在引用着它。当服务有不止一个引用的时候,这些引用被平等对待。
利用包环境对象BundleContext 的取得服务引用方法getServiceReference 或getServiceReferences来得到服务引用对象ServiceReference。取得服务引用方法getServiceReference返回一个服务引用,而getServiceReferences 返回满足条件的一个引用数组。因为框架是不断登记、启动、停止服务的动态环境,所以,你可能会想着用getServiceReferences,如代码示例1-9所示。
代码示例 1-9 在激活器类Activator 里取得服务引用(club/Activator.java)
① ② ③ ④ |
package club; import org.osgi.framework.BundleActivator; import org.osgi.framework.BundleContext; import org.osgi.framework.BundleException; import org.osgi.framework.ServiceReference; import org.osgi.framework.InvalidSyntaxException; import greeting2.service.GreetingService; public class Activator implements BundleActivator { public void start(BundleContext ctxt) throws BundleException { try { ServiceReference[ ] casualRefs = ctxt.getServiceReferences( "greeting2.service.GreetingService", "(description=casual)" ); GreetingService greetingSvc = (GreetingService) ctxt.getService( casualRefs[0] ); greetingSvc.greet("Bill", "Gates", "Chairman"); } catch (InvalidSyntaxException e) { throw new BundleException("Invalid LDAP filter", e); } } public void stop(BundleContext ctxt) throws BundleException { } } |
在俱乐部包club 启动时,它取得在JES框架中运行的所有所有随意问候服务CasualGreetingImpl的引用①。俱乐部包club用二个参数调用取得服务引用方法getServiceReferences —一个参数是问候服务GreetingService的完整规范名称,另一个是LDAP过滤器,用来随意问候实现CasualGreetingImpl登记时使用的属性。
这个方法需要使用LDAP过滤器,因为我们知道, JES框架中,在问候服务GreetingService接口下面,登记了二个服务。在这个例子里,LDAP过滤器的参数是"(description=casual)"①。取得服务引用方法getServiceReferences的过滤器参数有自己的语法规则,在Javadoc API文档的包环境BundleContext 接口中有详细说明。
在拥有了服务引用对象ServiceReference 的数组之后,包就调用数组中第一个元素的取得服务方法getService ,取得随意问候服务②,并把这个服务抛给服务对象GreetingService,后者是服务登记使用的接口类型。因为问候服务GreetingService 登记在框架里,并且俱乐部包club在它的清单文件里声明它导入问候服务GreetingService,所以JES框架可以满足这个请求。
然后启动方法start 用服务的greet 方法③,在包启动的时候,向一位著名的俱乐部会员显示随意的欢迎信息。激活器类Activator需要处理LDAP过滤器参数中的语法错误,所以catch子句会捕捉无效语法异常
InvalidSyntaxException ,并用消息Invalid LDAP filter(无效LDAP过滤器)抛出这个异常④。
当然,这个包也需要一个清单文件。清单文件需要指定包激活器类的名称和包依赖的其它包,在这个例子里,它依赖的包是greeting2.service。
① ② |
Bundle-Activator: club.Activator Import-Package: greeting2.service |
清单文件中的导入包头Import-Package②指定俱乐部包需要的Java(package)。在JES框架启动包时,框架会保证包greeting2 已经导出了greeting2.service。然后,框架才用指定的激活器类Activator①激活俱乐部包club。
1. 打开 MS-DOS 命令窗口,进入正确的教程目录:
C: cd jes2.0docs utorialclub
2. 建立JAR文件:
C: nmake
JAR文件建立在jes2.0docs utorialuildundlesclub.jar.
3. 启动JES框架: 从开始菜单,选择程序,然后Java嵌入服务器 2.0,Java 嵌入服务器 2.0 框架。
4. 在框架窗口中,安装刚刚建立的包:
> install file:/jes2.0/docs/tutorial/build/bundles/club.jar
5. 取包刚安装的包的ID,启动包:
> bundles > start bundleID
将会看到欢迎信息:
Hey, I’m Scott. Nice to meet you, Bill
6. 检查导出的包:
> exportedpackages Package: greeting2.service (0.0.0) Exported by: 10 (file:/home/sahmed/kmakebuild/product/docs/tutorial/build/bundles/greeting2.jar) Imported by: 12 (file:/home/sahmed/kmakebuild/product/docs/tutorial/build/bundles/greeting3.jar) 13 (file:/home/sahmed/kmakebuild/product/docs/tutorial/build/bundles/club.jar)
这显示greeting2.service 已经由greeting2.jar导出,并由club.jar导入。
7. 停止包:
> bundles > stop bundleID