【发布时间】: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 中实现这一点?提醒一下,这是我的要求列表:
- 轻松启用和禁用
REngineProvider捆绑包。客户端代码将只使用另一个提供程序。 - 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 对象,或者设置一个异常来解释创建失败的原因。
对于客户端,现在使用 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