我正在Eclipse RCP中开发应用程序。我需要有关服务设计的设计决策方面的帮助。
我有一些捆绑包,用于向其他模块提供REngine
对象。 REngine
是计算引擎的接口,可以通过多种方式实现。捆绑包通过连接到远程服务器或启动本地计算线程来提供REngine的实例。有些捆绑软件需要通过GUI进行配置(但也需要在无头平台上可用)。客户端捆绑包可以请求多个REngine
对象进行并行计算。
我目前正在注册这些模块以提供REngine
服务。该服务由ServiceFactory创建,该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对象是 Activity 对象,应该在不再需要它们时将其释放。
但是,一个注册的服务每个捆绑包只能提供一个服务实例。第二次请求该服务时,将返回一个缓存实例(而不是创建一个新实例)。这不符合我的要求;一个包应该能够从同一个提供者那里获取多个REngine对象。
我已经看过其他OSGi框架类,但似乎无济于事。另一种选择是白板模型,但是注册由REngineProvider捆绑包使用的REngineRequestService发出实时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
无效。 最佳答案
您需要的是ComponentFactory中的Declarative Services。大多数情况下,您应该使用DS而不是手动注册和查找服务。
提供方应注册REngine工厂服务(您不必自己实施工厂,DS会为您完成)。结束者应该声明对REngine服务的一对多依赖性。在运行时,将注入所有可用的工厂,并且消费者可以遍历它们来创建实际的REngine实例。