我刚开始使用Equinox和Eclipse PDE来了解OSGI和声明性服务(DS)。
我有2个捆绑包,A和B。
捆绑软件A公开了捆绑软件B使用的组件。两个捆绑软件还将该服务再次公开给OSGI服务注册表。
到目前为止,一切工作正常,Equinox将组件连接在一起,这意味着Equinox实例化了Bundle A和Bundle B(通过调用默认构造函数),然后使用bind/unbind方法进行了绑定(bind)。
现在,随着Equinox创建这些组件/服务的实例,我想知道获得该实例的最佳方法是什么?
因此,假设存在第三类类,该类未由OSGI实例化:
类别WantsToUseComponentB {
公共(public)无效doSomethingWithComponentB(){
//如何获取componentB ???像这样的东西?
ComponentB组件=(ComponentB)someComponentRegistry.getComponent(ComponentB.class.getName());
}
我现在看到以下选项:
1.在激活器中使用ServiceTracker来获取ComponentBundleA.class.getName()的服务(我已经尝试过了,并且可以正常工作,但对我来说似乎很麻烦),并可以通过静态工厂方法使用它
公共(public)类激活器{
私有(private)静态ServiceTracker组件BServiceTracker;
公共(public)无效开始(BundleContext上下文){
componentBServiceTracker = new ServiceTracker(context,ComponentB.class.getName(),null);
}
公共(public)静态ComponentB getComponentB(){
返回(ComponentB)componentBServiceTracker.getService();
};
}
2.创建某种注册表,每个组件在调用activate()方法后立即进行注册。
公共(public)ComponentB {
公共(public)无效绑定(bind)(ComponentA componentA){
someRegistry.registerComponent(this);
}
或者
公共(public)ComponentB {
公共(public)无效激活(ComponentContext上下文){
someRegistry.registerComponent(this);
}
}
}
3.使用osgi/equinox里面的现有注册表,其中包含那些实例?我的意思是OSGI已经在创建实例并将它们连接在一起,因此它的对象已经在某个地方。但是哪里?我怎样才能得到它们?
结论
类 WantsToUseComponentB (不是组件,也不由OSGI实例化)从哪里获取ComponentB的实例?是否有任何模式或最佳实践?就像我说的那样,我设法在Activator中使用了ServiceTracker,但是我认为没有它是可能的。
我要找的实际上是诸如Springframework的BeanContainer之类的东西,在这里我可以说诸如Container.getBean(ComponentA.BEAN_NAME)之类的东西。但是我不想使用Spring DS。
我希望这已经足够清楚了。否则,我也可以发布一些源代码以进行更详细的说明。
谢谢
克里斯多夫
更新:
回答尼尔的评论:
嗯不知道。也许有办法,但是我需要将整个框架重构为基于DS,这样就不再有“新的MyThirdClass(arg1,arg2)”语句。
真的不知道该怎么做,但是我在DS中阅读了有关ComponentFactories的内容。因此,与其做一个
MyThirdClass对象=新的MyThirdClass(arg1,arg2);
我可能会做一个
ComponentFactory myThirdClassFactory = myThirdClassServiceTracker.getService();//返回一个
如果(myThirdClassFactory!= null){
MyThirdClass对象= objectFactory.newInstance();
object.setArg1(“arg1”);
object.setArg2(“arg2”);
}
别的{
//在这里我可以假设ComponentA或B的某些服务消失了,因此MyThirdClass Componenent无法创建,因为缺少依赖项?
}
在撰写本文时,我还不确定如何使用ComponentFactories,但这应该是某种伪代码:)
谢谢
克里斯多夫
最佳答案
克里斯多夫
感谢您针对原始版本澄清此问题,但我认为您仍然需要说明为什么无法通过DS之类的方法创建第三类。
DS导致组件作为服务发布,因此从DS中“获取”任何组件的唯一方法是通过服务注册表进行访问。不幸的是,由于服务注册表是动态的,因此可能难以使用较低级别的API正确使用服务注册表,因此您必须应对在您希望它们可用之时恰好服务消失或不可用的可能性,依此类推。 。这就是存在DS的原因:DS为您提供了一个抽象概念,用于根据服务和基于组件引用的服务的可用性来管理组件的生命周期。
如果您确实需要在不使用DS或类似工具的情况下访问服务(并且有很多类似“事物”的选择,例如Spring-DM,iPOJO,Guice/Peaberry等),则应该使用ServiceTracker。我同意会有很多开销-再次,这就是为什么DS存在的原因。
要回答您的建议否(2),否,您不应该创建自己的服务注册表,因为服务注册表已经存在。如果创建了一个单独的并行注册表,则仍然必须处理所有动态,但是必须在两个地方而不是一个地方进行处理。建议(3)也是如此。
我希望这有帮助。
问候,
尼尔
更新:顺便说一句,尽管Spring具有Container.getBean()后门,但您注意到在所有Spring文档中,强烈建议不要使用该后门:要获取Spring bean,只需创建另一个引用它的bean。同样适用于DS,即获取DS组件的最佳方法是创建另一个DS组件。
还要注意,在OSGi世界中,即使您使用的是Spring-DM,也没有简单的方法来调用getBean(),因为您需要首先掌握Spring ApplicationContext。这本身就是OSGi服务,那么如何获得该服务?