12.2. 导出服务

概述

这部分描述了如何将 Java 对象导出到 OSGi 服务注册表,从而使它可作为 service 到 OSGi 容器中其他捆绑包的服务。

使用单个接口导出

要在单一接口名称下将服务导出到 OSGi 服务注册表,请定义一个 service 元素来引用相关服务 bean,使用 ref 属性指定发布的接口,并使用 interface 属性指定公布的 接口

例如,您可以使用 例 12.1 “使用单一接口导出服务示例” 中显示的 Blueprint 配置代码,在 org.fusesource.example.Account 接口名称下导出 SavingsAccountImpl 类的实例。

例 12.1. 使用单一接口导出服务示例

<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0">

  <bean id="savings" class="org.fusesource.example.SavingsAccountImpl"/>

  <service ref="savings" interface="org.fusesource.example.Account"/>

</blueprint>

其中 ref 属性指定对应 bean 实例的 ID,而 interface 属性指定服务在 OSGi 服务注册表中注册的公共 Java 接口的名称。本例中使用的类和接口显示在中 例 12.2 “帐户类和接口示例”

例 12.2. 帐户类和接口示例

package org.fusesource.example

public interface Account { ... }

public interface SavingsAccount { ... }

public interface CheckingAccount { ... }

public class SavingsAccountImpl implements SavingsAccount
{
    ...
}

public class CheckingAccountImpl implements CheckingAccount
{
    ...
}

使用多个接口导出

要将服务导出到多个接口名称下的 OSGi 服务注册表,请定义一个 service 元素来引用相关服务 bean,使用 ref 属性指定公布的接口,并使用 interfaces 子元素指定发布的接口。

例如,您可以使用以下 Blueprint 配置代码在公共 Java 接口列表下导出 Savings Account Impl 类的实例:

<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0">
  <bean id="savings" class="org.fusesource.example.SavingsAccountImpl"/>
  <service ref="savings">
    <interfaces>
      <value>org.fusesource.example.Account</value>
      <value>org.fusesource.example.SavingsAccount</value>
    </interfaces>
  </service>
  ...
</blueprint>
注意

interface 属性和 interfaces 元素不能在同一 service 元素中同时使用。您必须使用一个或多个.

使用自动导出导出

如果要在 其所有 实施的公共 Java 接口下将服务导出到 OSGi 服务注册表,则可以使用 auto-export 属性完成此任务的简单方法。

例如,要在其所有实施的公共接口下导出 SavingsAccountImpl 类的实例,请使用以下 Blueprint 配置代码:

<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0">
  <bean id="savings" class="org.fusesource.example.SavingsAccountImpl"/>
  <service ref="savings" auto-export="interfaces"/>
  ...
</blueprint>

其中,auto-export 属性 的接口 值表示 Blueprint 应注册 SavingsAccountImpl 实施的所有公共接口。auto-export 属性可以具有以下有效值:

disabled
禁用自动导出。这是默认值。
interfaces
将服务注册到其所有实施的公共 Java 接口下。
class-hierarchy
将服务注册到其自己的类型(class),并在所有 super-types (super-classes)下注册,但对象类除外。
all-classes
class-hierarchy 选项类似,但还包括所有实施的公共 Java 接口。

设置服务属性

OSGi 服务注册表还允许您将服务属性与注册 的服务 相关联。然后,服务的客户端可以使用服务属性来搜索或过滤服务。要将服务属性与导出的服务关联,请添加一个 service-properties 子元素,其中包含一个或多个 beans:entry 元素(每个服务属性有一个 beans:entry 元素)。

例如,要将 bank.name 字符串属性与节省帐户服务相关联,您可以使用以下 Blueprint 配置:

<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
           xmlns:beans="http://www.springframework.org/schema/beans"
           ...>
  ...
  <service ref="savings" auto-export="interfaces">
    <service-properties>
      <beans:entry key="bank.name" value="HighStreetBank"/>
    </service-properties>
  </service>
  ...
</blueprint>

其中 bank.name 字符串属性具有值 HighStreetBank。可以定义字符串以外的类型的服务属性:即,也支持原语类型、数组和集合。有关如何定义这些类型的详情,请参阅 Spring 参考指南 中的 控制公告属性 集。

注意

条目 元素 ought 属于 Blueprint 命名空间。Spring 的蓝图实现中的 beans:entry 元素的使用是非标准。

默认服务属性

使用 service 元素导出服务时可能会自动设置两个服务属性,如下所示:

  • osgi.service.blueprint.compname-is 始终设置为服务的 bean 元素的 id,除非 bean 被内联(即,bean 被定义为 service 元素的子元素)。内联 Bean 始终是匿名的。
  • 如果 ranking 属性为零,则会自动设置 service.ranking-is。

指定等级属性

如果捆绑包在服务 registry 中查找服务并找到多个匹配服务,您可以使用等级来确定返回哪些服务。规则是,每当查找与多个服务匹配时,会返回具有最高等级的服务。服务等级可以是任何非负整数,0 是默认值。您可以通过在 service 元素上设置 ranking 属性来指定服务等级,例如:

<service ref="savings" interface="org.fusesource.example.Account" ranking="10"/>

指定注册监听程序

如果要跟踪服务注册和未注册事件,您可以定义接收 注册和未注册事件通知的注册监听程序 回调 Bean。要定义注册监听程序,请在 service 元素中添加 registration-listener 子元素。

例如,以下 Blueprint 配置定义了一个监听器 bean bean, listenerBean,它由 registration-listener 元素引用,以便在 帐户 服务注册或取消注册时监听程序 bean 接收回调:

<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0" ...>
  ...
  <bean id="listenerBean" class="org.fusesource.example.Listener"/>

  <service ref="savings" auto-export="interfaces">
    <registration-listener
        ref="listenerBean"
        registration-method="register"
        unregistration-method="unregister"/>
  </service>
  ...
</blueprint>

其中 registration-listener 元素的 ref 属性引用监听器 bean 的 idregistration-method 属性指定接收注册回调的监听程序方法的名称,unregistration-method 属性指定接收未注册回调的监听程序方法的名称。

以下 Java 代码显示了一个 Listener 类的示例定义,用于接收注册和未注册事件通知:

package org.fusesource.example;

public class Listener
{
    public void register(Account service, java.util.Map serviceProperties) {
        ...
    }

    public void unregister(Account service, java.util.Map serviceProperties) {
        ...
    }
}

方法名称 registerunregister 分别由 registration-methodunregistration-method 属性指定。这些方法的签名必须符合以下语法:

  • 第一方法参数- 从服务对象类型分配的任何类型 T。换句话说,服务类或由服务类实施的任何接口的超级类型类。此参数包含服务实例,除非服务 bean 声明了要 原型化 的范围,在这种情况下,此参数为 null (当范围是 原型 的时,在注册时没有服务实例可用)。
  • 第二种方法参数- 必须是 java.util.Map 类型或 java.util.Dictionary 类型。此映射包含与此服务注册关联的服务属性。