2017-08-07 85 views
0

我在使用通过Karaf使用OSGi声明式服务时加载组件的顺序时遇到问题。声明式服务引用多个引用和依赖关系

予有这种情况:

@Component 
public class A implements IA 
{ 
    doSomething() {...} 
} 


@Component 
public class B implements IB 
{} 

@Component 
public class C implements IC 
{ 
    @Reference 
    IA a 

    @Reference 
    (cardinality = ReferenceCardinality.MULTIPLE, 
    policyOption = ReferencePolicyOption.GREEDY, 
    unbind = "doUnRegister") 
    void doRegister(IB b) 
    { 
    a.doSomething() 
    } 

    void doUnregister(IB b) 
    { 
    ... 
    } 
} 

A,B,和C是三种不同的束。

当启动Karaf时,B被注册并且调用doRegister。但是:服务A没有准备好(a为空)。

我试过如下:

  1. 组A的启动级别,以低于B低的东西......没在工作列表工作
  2. 皮卡B的注册和实际使用一之后当C被激活时。没有工作和代码混乱。
  3. 通过doRegister注释找到了一个写这个需求的方法 - 不可能。
  4. 我试图使用服务定位器并通过C - DID NOT WORK上的激活方法获取上下文,它使Karaf崩溃。

我必须明确地遗漏一些东西,有没有人遇到类似的问题,并找到了解决办法?

UPDATE: 参考文献A a改为IA a。在参考文献B()上添加了被遗忘的信息。

+0

您的示例类是否完整? B可能实现和接口,A不? –

+0

谢谢指出。但是,A,B和C是由接口支持的,问题依然存在。 –

+0

你可以发布一个完整的小例子到github或类似的吗? –

回答

0

根据您提供的示例代码,C不会被激活,直到AB存在,因为引用AB是静态的,强制性的引用。所以开始订购是不相关的。

此外,引用是按照它们写入组件描述XML的顺序设置的。当Bnd将批注处理到组件描述XML中时,它会按参考名称的顺序写入参考。引用名称可以明确设置,并且默认为注释成员的名称。因此,在您的示例代码中,a出现在doRegister之前,因此在调用doRegister之前将设置字段a

我的猜测是,在努力减少实际代码到这个例子中,你已经失去了一些重要的信息来理解你的问题。这将包括您的参考的静态/动态和强制性/可选性以及参考名称。

+0

更新:我更新了示例程序,更详细地介绍了引用注释和正确使用接口。 –

+0

ReferenceCardinality.MULTIPLE是0..n。因此,如果组件C在组件B之前启动,那么C的引用将很乐意被零Bs满足。此外,如果查看为组件C生成的组件描述XML,则应该看到字段A的引用元素位于绑定方法doRegister的引用元素之前。这意味着在B被绑定并且doRegister被调用之前,A将被绑定并成为一个集合。 –