【问题标题】:OSGi services architecture: creation of service at request of consumerOSGi 服务架构:根据消费者的请求创建服务
【发布时间】:2012-04-12 00:16:37
【问题描述】:

我正在 Eclipse RCP 中开发一个应用程序。我需要有关服务设计的设计决策方面的帮助。

我有一些包用于向其他模块提供REngine 对象。 REngine 是计算引擎的接口,可以通过多种方式实现。捆绑包通过连接到远程服务器或启动本地计算线程来提供 REngine 实例。一些捆绑包需要通过 GUI 进行配置(但也需要在无头平台上可用)。客户端 Bundle 可以请求多个 REngine 对象进行并行计算。

我目前注册这些模块以提供REngine 服务。该服务由 ServiceFactory 创建,它启动本地计算实例或远程(服务器)实例。客户端负责尝试REngine类的所有服务注册并选择正确的。

执行此操作的代码可以总结如下:

class API.REngine { ... }

class REngineProvider.Activator {
    public void start(BundleContext ctx) {
      ctx.registerService(REngine.class.getName(), new REngineFactory(), null);
    }
}
class REngineProvider.REngineFactory implements ServiceFactory {
    public Object getService(Bundle bundle, ServiceReference reference) {
      return new MyREngineImplementation();
    }
    public void ungetService(REngine service) {
       service.releaseAssociatedResources();
    }
}

class RConsumer.Class {
    REngine getREngine() {
        ServiceReference[] references = bundleContext.getAllServiceReferences(REngine.class.getName(), null);
        for(ServiceReference ref: references) {
            try {
            return bundleContext.getService(ref);
            } catch (Exception e) {} // too bad, try the next one
        }
    }
}

我想保留这个模型。很高兴 OSGi 服务规范符合我的业务需求,即 REngine 对象是活的对象,当不再需要它们时应该释放它们。

但是,一个注册服务只能为每个捆绑提供一个服务实例。第二次请求服务时,会返回一个缓存实例(而不是创建一个新实例)。这不符合我的要求;一个包应该能够从同一个提供者获取多个 REngine 对象。

我已经查看了其他 OSGi 框架类,但似乎没有任何帮助。替代方案是白板模型,但注册一个 REngineProvider 包使用的 REngineRequestService 来提供一个实时 REngine 似乎很奇怪。

如何在 OSGi 中实现这一点?提醒一下,这是我的要求列表:

  1. 轻松启用和禁用REngineProvider 捆绑包。客户端代码将只使用另一个提供程序。
  2. REngineProvider 包的配置。
  3. 每个客户端捆绑包有多个 REngine 实例。
  4. REngine 实例的显式发布
  5. REngine 创建可能会失败。客户端模块应该能够知道原因。

只是为了添加我选择作为未来参考的解决方案。似乎 OSGi 服务平台不是为“请求服务”而设计的。提供者包创建服务,客户端包可以找到和使用服务。无法根据用户请求为服务提供自动“工厂”。

选择的解决方案涉及OSGi whiteboard model。乍一看,这似乎很难管理,但Blueprint 可以提供很大帮助!

提供者 blueprint.xml 文件:

<reference-list interface="org.application.REngineRequest"
          availability="optional">
  <reference-listener 
          bind-method="bind" unbind-method="unbind">
      <bean class="org.provider.REngineProvider"/>        
  </reference-listener>

REngineRequest 类是一个共享 API 类,允许提供者输入他的 REngine 对象,或者设置一个异常来解释创建失败的原因。

对于客户端,现在使用 REngine 就像做一样简单:

REngineRequest req = new REngineRequest();
ServiceRegistration reg = bundleContext.registerService(req, REngineRequest.class.getName(), engineCreationProperties);
req.getEngine().doSomeStuff();
reg.unregister();

我们假设在客户端使用 REngine 时提供程序永远不会停止。如果是这样,REngine 就会失效。

【问题讨论】:

    标签: java eclipse-rcp osgi


    【解决方案1】:

    Declarative Services 中的ComponentFactory 是您所需要的。大多数情况下,您应该使用 DS 而不是手动注册和查找服务。

    提供方应注册 REngine 工厂服务(您不必自己实现工厂,DS 会为您完成)。消费者应该声明对 REngine 服务的一对多依赖。在运行时,所有可用的工厂都将被注入,消费者可以通过它们创建实际的 REngine 实例。

    【讨论】:

    • 您会推荐 BluePrint 和 PROTOTYPE 注释而不是 DS 吗?我很难看出区别。
    • 我打算建议蓝图和原型范围。 Blueprint 比声明式服务有更多的旋钮,这可能对您有用。
    • 不幸的是,我在创建对象时需要上下文(属性)。我不能指定一个简单的工厂方法,但必须指定一个实例化的类,这很麻烦。让我们希望 Blueprint 有这样的东西!
    • Blueprint 允许您使用 factory-method 属性为 bean 类声明一个工厂。您可以使用静态或实例工厂。您还可以注入属性并传递构造函数参数,包括捆绑上下文的特殊属性。
    • ibm.com/developerworks/opensource/library/os-osgiblueprint/… 有一个很好的蓝图教程,Tim 和我在 Enterprise OSGi in Action 中有一章(嗯,真的是两章)。
    【解决方案2】:

    两年前,我尝试创建真正的服务工厂,后来成为参数化服务。但是,分析后发现什么都不需要,只需将工厂注册为服务即可。

    但是。

    我对您的服务知之甚少,但听起来您可以通过从客户端捆绑包中删除控制来显着简化事情,客户端捆绑包应该只使用服务注册表中可用的任何 REngine 服务,可能带有一个属性如果有多个需要 REngine 的包并且它们不应该共享同一个 REngine(这种情况很少会发生),则表明它的使用类型。

    如果该模型可行,它通常会大大简化。然后,我通常将 DS 与驱动实例的 Configuration Admin 配置一起使用(DS 最有用的方面之一,请参阅http://www.aqute.biz/Bnd/Components)。通过元类型集成,您甚至可以获得编辑配置属性的用户界面。

    【讨论】:

    • 这可能是最简单的实现。获取服务的捆绑包将触发新服务的注册。
    • 啊哈!因此,解决方案是使用配置管理提供“我希望您创建以下 REngine 实例”的列表,然后获取服务。我可能可以通过发布异常而不是 REngine 对象本身来传达异常。唯一剩下的问题是请求服务和获得服务之间的时间问题。
    • 获取服务不会触发新的注册。有两个步骤:客户端包获取注册表中的任何内容,配置管理员定义通过 DS 组件可用的内容。对于 DS 组件,时间无关紧要,因为您表达了依赖关系。除非您是一些中间件开发人员,否则切勿使用 ServiceReferences ... DS 非常干净,尤其是带有注释
    【解决方案3】:

    一种解决方案是将 REngineFactory 注册为服务而不是 REngine 实现本身,并从 getService 方法返回工厂。这样客户就可以查找工厂,并在成功找到工厂后,使用它来获得新的 REngine 实现。

    【讨论】:

      猜你喜欢
      • 2013-12-29
      • 2021-07-23
      • 1970-01-01
      • 2015-04-16
      • 2016-04-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-08-16
      相关资源
      最近更新 更多