OSGi服务架构:根据消费者的要求创建服务

par*_*tje 5 java osgi eclipse-rcp

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

我有一些用于REngine向其他模块提供对象的bundle .它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
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

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

但是,注册服务每个包只能提供一个服务实例.第二次请求服务时,将返回一个缓存的实例(而不是创建一个新的实例).这与我的要求不符; 一个bundle应该能够从同一个提供者那里获得多个REngine对象.

我已经看过其他OSGi框架类,但似乎没有任何帮助.另一种选择是白板模型,但是注册一个REngineRequest服务似乎很奇怪,它由REngineProvider包用来提供一个实时的REngine.

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

  1. 轻松启用和禁用REngineProvider捆绑包.客户端代码将仅使用其他提供程序.
  2. 配置REngineProvider捆绑包.
  3. REngine每个客户端捆绑包多个实例
  4. 明确释放REngine实例
  5. REngine创作可能会失败.客户端模块应该能够知道原因.

只是添加我选择的解决方案作为未来参考.似乎OSGi服务平台不是为"请求服务"而制作的.它是创建服务的提供程序包,以及可以查找和使用服务的客户端包.不能为每个用户请求提供服务的自动"工厂".

选择的解决方案涉及OSGi白板模型.乍一看,这似乎很难管理,但Blueprint可以帮助很多!

Provider 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>
Run Code Online (Sandbox Code Playgroud)

该类REngineRequest是一个共享API类,允许提供程序输入其REngine对象,或设置一个Exception来解释创建无效的原因.

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

REngineRequest req = new REngineRequest();
ServiceRegistration reg = bundleContext.registerService(req, REngineRequest.class.getName(), engineCreationProperties);
req.getEngine().doSomeStuff();
reg.unregister();
Run Code Online (Sandbox Code Playgroud)

我们假设提供者在客户端使用REngine时永远不会停止.如果是,则REngine变为无效.

Iva*_*rov 3

声明性服务中的ComponentFactory正是您所需要的。大多数时候,您应该使用 DS,而不是手动注册和查找服务。

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