2013-08-29 39 views
2

BundleActivator中使用OSGi ServiceTracker的最佳做法是什麼?我在網絡上看到了一些示例,它們在start方法中打開跟蹤器,將其存儲在實例變量中,然後在stop方法中關閉它,使其在包的生命週期中保持打開狀態。這是否合適?我一直在編寫代碼,以便在需要時打開跟蹤器,獲取服務並使用它,然後關閉跟蹤器。當然,如果我想稍後使用它,則需要將BundleContext本身存儲在實例變量中。因爲我必須存儲一個或另一個,所以我可能沒有太大的區別。我應該讓OSGi ServiceTracker保持打開狀態,還是在使用後關閉它?

在一個相關的問題中,如果我每次需要打開跟蹤器,是否需要在使用我從中獲得的服務時打開跟蹤器,還是可以打開跟蹤器,獲取服務,關閉跟蹤器,然後使用該服務?我沒有看到我在使用該服務之前無法關閉跟蹤器的原因。

回答

2

如果你想打開一個跟蹤器只是爲了一個服務電話,你根本不需要跟蹤器。你所要做的就是通過bundleContext獲取服務,並在完成時取消它。

ServiceTracker不僅適用於調用服務,而且還可以調用waitForService方法,以便您的線程將一直等到有好的服務可用時爲止。

如果您使用服務跟蹤器,並且每次調用getService()以獲取服務對象時,您可能不會調用相同的服務。服務跟蹤器默認跟蹤每個滿足過濾標準的服務,因此如果您上次使用的服務在下次再次提供服務時未註冊。

如果您從服務跟蹤器子類或編寫ServiceTrackerCustomizer,您可以捕獲服務跟蹤事件。例如。您可以創建一個邏輯,在您每次註冊符合要求的服務時提供自己的服務對象。您也可以指定應跟蹤哪些服務(您在addedService中返回null,而不會跟蹤該服務)。

簡而言之:

  • 如果你要調用一個服務只有一次或兩次(例如,當您的包開始或停止),你可以簡單地通過上下文獲得服務和unget它
  • 如果你想在你的包是主動打電話給服務多少次,或者您想基於服務可用性的事件來創建自定義的邏輯,使用服務跟蹤

如果你選擇第一個選項,也絕不能將一個服務對象在一個成員變量中更長一段時間竹葉提取!在第一種選擇的情況下,您應該立即取消服務,只要您不再需要它。服務跟蹤器也是一樣。每次調用getService方法時,不要將其保存在類的成員變量中,因爲它可能會在您再次需要時取消註冊。

其他OSGi專家在這裏是在stackoverflow(設計OSGi的人),所以他們可以給出更具體的答案。

5

服務來來去去 - 作爲OSGi開發人員的職責是隻有在服務已經發布時才使用服務,更重要的是在未發佈服務時發佈服務。如果您在未發佈服務後繼續使用服務,則可能會發生不可預知的錯誤。至少你會導致與該服務實例關聯的堆空間被固定在內存中,這會破壞OSGi動態安裝和卸載軟件包的能力。

所以,你問你是否應該在使用該服務之前關閉ServiceTracker:我的回答是。 ServiceTracker作爲當前服務的「智能指針」,它管理所有監聽器等,以便在服務消失時得到通知。如果關閉跟蹤器,則不再保持服務狀態的最新狀態,那麼如何知道它是否仍然有效?

了使用ServiceTracker的理想模式 - 假設跟蹤保持整個開放 - 如下:

{  
    Service svc = tracker.getService(); 
    svc.doSomething(); 
} 
// 'svc' is now forgotten, and may be garbage collected 

也就是說,當你在跟蹤調用getService()您獲得實際的實例服務,但您應該儘快使用它,然後儘快將其忘記。您絕對不能將getService()的結果存儲在一個字段中,並堅持很長時間。

至於是否應打開,並立即關閉跟蹤器僅在需要時 - 不,這完全沒有必要這麼做。開放的追蹤器不消耗任何重要的資源,它僅僅意味着它被註冊爲一個監聽器,以便它知道服務何時來去。事實上,重複打開和關閉跟蹤器是無效的,因爲每次打開跟蹤器時,都必須與服務註冊表的當前狀態進行同步。這就是爲什麼您在示例中看到的模式通常是在激活束期間打開跟蹤器並將其保持打開狀態......這是最好的模式。

順便也沒有必要在你的BundleActivator.stop方法明確地關閉跟蹤。與您的跟蹤器相關的所有資源將在捆綁停止時自動清除。明確關閉的唯一原因是如果您有多個跟蹤器和/或服務註冊,並且您想控制清理的順序。

現在說了以上全部內容,我要去查一個手榴彈:請停止使用ServiceTracker這是一個非常低級的實用程序,只是很少需要,然後只在「管道」或基礎結構代碼中。大多數應用程序應該建立在更高級別的抽象層次上。我強烈建議使用聲明式服務,這比纏繞ServiceTracker更容易。

5

的服務跟蹤,最好的做法是使用聲明式服務。

對於專家:有一些高度專業化的情況下,服務跟蹤是非常有用的(並且一定要看!),但如果你要問這個問題比服務Tracker是不適合你。該服務Tracker是一個非常低的水平的方式與像聲明服務實現藍圖的實現中間件使用的服務工作等

+2

不錯的方式把它。 「如果你不得不問如何使用它,你就不應該使用它。」 :-) –

0

我覺得ServiceTracker的是同時使用的方法BundleActivator.start()內部和方法activate()內部服務有用Components

在初始化時使用它們的目的是爲了避免當我們正在過初始化捆綁使用服務可能造成的死鎖。

是否建議ServiceTrackers或基於DS的初始化時間有任何其他更好的模式?

相關問題