2009-07-09 97 views
4

我剛剛開始使用Equinox和Eclipse PDE開始使用OSGI和聲明式服務(DS)。OSGI聲明式服務(DS):什麼是使用服務組件實例的好方法

我有2個軟件包,A和B. 軟件包A公開了一個被軟件包B使用的組件。兩個軟件包也將此服務再次公開給OSGI服務註冊表。

到目前爲止一切正常,Equinox將組件連接在一起,這意味着Bundle A和Bundle B被Equinox實例化(通過調用默認構造函數),然後使用綁定/解除綁定方法進行連接。

現在,當Equinox創建這些組件/服務的實例時,我想知道獲取此實例的最佳方式是什麼?

所以假設有第三類類不是由OSGI實例:

Class WantsToUseComponentB{ 
public void doSomethingWithComponentB(){ 
// how do I get componentB??? Something like this maybe? 
ComponentB component = (ComponentB)someComponentRegistry.getComponent(ComponentB.class.getName()); 
}

我看到下面的選項現在:



1.使用在一個ServiceTracker的Activator獲得ComponentBundleA.class.getName()的服務(我已經嘗試過了,它可以工作,但它對我來說似乎有很多開銷),並通過一個靜態工廠方法

 
public class Activator{ 

    private static ServiceTracker componentBServiceTracker; 

    public void start(BundleContext context){ 

    componentBServiceTracker = new ServiceTracker(context, ComponentB.class.getName(),null); 
    } 

    public static ComponentB getComponentB(){ 
    return (ComponentB)componentBServiceTracker.getService(); 
    }; 

} 

2.創建某種註冊表的,其中每個組件寄存器只要activate()方法被調用。

 
public ComponentB{ 

public void bind(ComponentA componentA){ 
    someRegistry.registerComponent(this); 
} 

 
public ComponentB{ 

    public void activate(ComponentContext context){ 
     someRegistry.registerComponent(this); 
    } 

} 

}

3.使用現有的具有這些實例的OSGi /春分註冊表裏面的?我的意思是OSGI已經在創建實例並將它們連接在一起,所以它已經在某處存在對象。但是哪裏?我怎樣才能得到它們?

結論 哪裏類WantsToUseComponentB(這不是一個組件,並通過OSGI不實例)從獲得以componentB的實例?有沒有任何模式或最佳做法?正如我所說我設法在Activator中使用ServiceTracker,但是我認爲沒有它可能會有這種可能。

我在找的實際上就是Springframework的BeanContainer,在這裏我只能說一些類似於Container.getBean(ComponentA.BEAN_NAME)的東西。但我不想使用Spring DS。

我希望這已經夠清楚了。否則,我也可以發佈一些源代碼來更詳細地解釋。

感謝 克里斯托夫


更新: 回答尼爾的評論:

感謝澄清與原始版本的這個問題,但我認爲你還需要說明爲什麼第三類不能通過像DS那樣創建。

嗯不知道。也許有一種方法,但我需要重構我的整個框架以基於DS,以便不再有「新的MyThirdClass(arg1,arg2)」語句。 不知道該怎麼做,但我在DS中閱讀了一些關於ComponentFactories的內容。因此,而不是做一個

 
MyThirdClass object = new MyThirdClass(arg1, arg2); 

我可以做一個

 
ComponentFactory myThirdClassFactory = myThirdClassServiceTracker.getService(); // returns a 

if (myThirdClassFactory != null){ 
    MyThirdClass object = objectFactory.newInstance(); 

    object.setArg1("arg1"); 
    object.setArg2("arg2"); 
} 
else{ 
// here I can assume that some service of ComponentA or B went away so MyThirdClass Componenent cannot be created as there are missing dependencies? 

} 

在寫這篇文章的時候,我不知道到底如何使用ComponentFactories但是這應該是某種僞代碼:)

感謝 克里斯托夫

回答

5

克里斯托夫,

感謝澄清與原始版本的這個問題,但我認爲你還需要說明爲什麼第三類不能通過類似DS創建。

DS導致組件作爲服務發佈,因此從DS「獲取」任何組件的唯一方法是通過服務註冊表訪問它。不幸的是,由於服務註冊表是動態的,因此服務註冊表可能難以正確使用,因爲它是動態的,所以您必須應對服務在您希望它們可用的時刻消失或不可用的可能性,等等。這就是DS存在的原因:它爲您提供了取決於服務的抽象概念,並根據其參考的服務的可用性來管理組件的生命週期。

如果你確實需要訪問一個服務而不使用DS或類似的東西(並且有很多「類似的東西」的選擇,例如Spring-DM,iPOJO,Guice/Peaberry等),那麼你應該使用ServiceTracker。我同意有很多開銷 - 同樣,這也是DS存在的原因。

要回答你的建議no(2),不,你不應該創建自己的服務註冊表,因爲服務註冊表已經存在。如果你創建了一個單獨的並行註冊表,那麼你仍然必須處理所有的動態,但你必須在兩個地方而不是一個地方處理它。建議(3)同樣適用。

我希望這會有所幫助。

問候, 尼爾

更新:順便說一句,雖然春天有Container.getBean()後門程序,您會發現所有的Spring文檔中,強烈建議不要使用後門程序:獲得一個春天的擱置bean,只需創建另一個引用它的bean。這同樣適用於DS,即獲取DS組件的最佳方式是創建另一個DS組件。

另請注意,在OSGi世界中,即使您使用Spring-DM,也沒有簡單的方法來調用getBean(),因爲您需要首先獲得Spring ApplicationContext。這本身就是一個OSGi服務,那麼如何獲得該服務?

0

克里斯托夫, 不知道如果我真的能理解你的問題。 /ex。 束A被利用提供服務DS組成:

<service> 
    <provide interface="org.redview.lnf.services.IRedviewLnfSelectedService"/> 

束B需要使用DS組分此服務:

<implementation class="ekke.xyz.rcp.application.internal.XyzApplicationLnfComponent"/> 

只要包A提供的服務,Bundle B通過實現類的bind()方法「獲取」它:

public class XyzApplicationLnfComponent { 
public void bind(IRedviewLnfSelectedService lnfSelectedService) { 
    // here it is 
} 

希望這有助於 EKKE

+0

捆B也需要服務(在發佈我的答案後行已經「消失」了) ekkescorner 2009-07-09 10:41:51

+0

感謝Ekke的回答: 我更新了我的問題,提供了更多的細節和代碼示例。 什麼我感興趣的其實是第三類是這樣的:

Class WantsToUseComponentB{ public void doSomethingWithComponentB(){ // how do I get componentB??? Something like this maybe? ComponentB component = (ComponentB)someComponentRegistry.getComponent(ComponentB.class.getName()); } 
你能再看看嗎? 謝謝克里斯托夫 – Christoph 2009-07-09 11:01:59

相關問題