2009-07-09 95 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

相关问题