我正在Eclipse RCP中开发一个应用程序。我需要有关服务设计的设计决策方面的帮助。
我有一些bundle用于向其他模块提供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对象是生命对象,应该在不再需要时释放它们。
但是,注册服务每个捆绑包只能提供一个服务实例。第二次请求服务时,将返回一个缓存的实例(而不是创建一个新的实例)。这与我的要求不符;一个bundle应该能够从同一个提供者那里获得多个REngine对象。
我已经查看了其他OSGi框架类,但似乎没有任何帮助。另一种选择是白板模型,但是注册REngineRequest服务并使用REngineProvider包来提供实时REngine似乎很奇怪。
如何在OSGi中实现此功能?提醒一下,这是我的要求清单:
REngineProvider
个捆绑包。客户端代码将改为使用其他提供商。REngine
个实例。REngine
个实例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对象,或者设置一个Exception来解释创建不起作用的原因。
对于客户来说,使用REngine就像现在一样简单:
REngineRequest req = new REngineRequest();
ServiceRegistration reg = bundleContext.registerService(req, REngineRequest.class.getName(), engineCreationProperties);
req.getEngine().doSomeStuff();
reg.unregister();
我们假设提供商在客户端使用REngine时永远不会停止。如果是,则REngine
变为无效。
答案 0 :(得分:3)
供应商方应注册REngine工厂服务(您不必自己实施工厂,DS会为您执行此操作)。构造者应该声明对REngine服务的一对多依赖。在运行时,将注入所有可用的工厂,并且消费者可以通过它们来创建实际的REngine实例。
答案 1 :(得分:3)
两年前,我尝试创建真正的服务工厂,后来成为参数化服务。然而,经过分析后发现不需要任何东西,只需将工厂注册为服务。
然而
我对你的服务知之甚少,但听起来你可以通过从客户端包中删除控制来大大简化事情,客户端包应该只使用服务注册表中可用的任何REngine服务,也许是属性如果有多个捆绑包需要REngines并且它们不应共享相同的REngine(很少应该是这种情况),则表示其使用类型。
如果可以使用该模型,通常会大大简化。我通常会使用带有驱动实例的配置管理配置的DS(DS最有用的方面之一,请参阅http://www.aqute.biz/Bnd/Components)。通过元类型集成,您甚至可以获得用户界面来编辑配置属性。
答案 2 :(得分:1)
一种解决方案是将REngineFactory注册为服务而不是REngine实现本身,并从getService方法返回工厂。通过这种方式,客户可以查找工厂,并在成功找到工厂后,使用它来获得新的REngine实现。