我正在Eclipse RCP中開發應用程序。我需要關於服務設計的設計決定方面的幫助。OSGi服務體系結構:根據消費者的要求創建服務
我有一些捆綁被用來提供一個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框架類,但似乎沒有任何幫助。另一種方法是白板模式,但註冊REngineProvider軟件包使用的REngineRequestService來發出實時REngine似乎很奇怪。
如何在OSGi中實現這個功能?提醒一下,這裏是我的要求列表:
- 易於啓用和禁用
REngineProvider
捆綁軟件。客戶端代碼將只使用另一個提供者。 - 配置REngineProvider包。
- 每個客戶端軟件包多個
REngine
實例。 - 顯式發佈的
REngine
實例 REngine
創建失敗。客戶端模塊應該能夠知道原因。
我想補充我選擇作爲未來的參考解決方案。看來OSGi服務平臺不是用於「請求服務」。它是創建服務的提供程序包,以及可以找到並使用服務的客戶端包。無法爲每個用戶的請求提供服務的自動「工廠」。
所選解決方案涉及OSGi whiteboard model。一見鍾情,這似乎很難管理,但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
將無效。
您會推薦使用BluePrint和PROTOTYPE批註代替DS嗎?我很難看出差異。 – parasietje 2012-03-28 15:47:48
我正在建議藍圖和原型範圍。藍圖擁有比聲明式服務更多的旋鈕,這可能對您有用。 – 2012-03-28 16:16:29
不幸的是,我創建我的對象時需要上下文(屬性)。我不能指定一個簡單的工廠方法,但必須指定一個實例化的類。讓我們希望藍圖有這樣的東西! – parasietje 2012-03-28 18:04:29