OSGi:在声明性服务组件激活方法中注册服务有效吗?

OSGi:在声明性服务组件激活方法中注册服务有效吗?,osgi,declarative-services,Osgi,Declarative Services,这是另一个问题的副本,但复制自另一个问题: 我遇到了Felix SCR的问题,我从中得到了以下信息: ServiceFactory.getService()导致了一个循环 出现这种情况的原因是,在激活方法中,将其称为ServiceAImpl(提供ServiceA),服务注册另一个服务,将其称为ServiceB 我有另一个服务组件,称为ServiceCImpl,它同时依赖于ServiceA和ServiceB。通过ServiceAImpl注册ServiceB,ServiceCImpl已经得到满足,在

这是另一个问题的副本,但复制自另一个问题:

我遇到了Felix SCR的问题,我从中得到了以下信息:

ServiceFactory.getService()导致了一个循环

出现这种情况的原因是,在激活方法中,将其称为ServiceAImpl(提供ServiceA),服务注册另一个服务,将其称为ServiceB

我有另一个服务组件,称为ServiceCImpl,它同时依赖于ServiceA和ServiceB。通过ServiceAImpl注册ServiceB,ServiceCImpl已经得到满足,在激活ServiceAImpl的同一调用中,ServiceCImpl绑定方法被调用。调用ServiceA的绑定方法时,会检测到循环,并且组件无法初始化

也许有一种方法允许SCR等待绑定ServiceCImpl,或者我需要以不同的方式注册ServiceB

我想没有意义的是,为什么Felix SCR会在ServiceAImpl的激活方法中激活ServiceCImpl。在激活方法退出之前,我认为ServiceCImpl不会被认为是满意的。也许这是一个在使用声明性服务的同时仍然直接向框架注册服务的问题

还没有尝试过其他SCR实现,比如Equinox的版本,但我可能会尝试一下,看看是否有区别,但也许有人知道这是OSGi还是Felix


附加信息:至于为什么ServiceB不是服务组件…ServiceA实际上有一个0..n的服务引用,对于另一个服务,称之为已服务。每次组件提供服务接口时,都会使用相同的服务对象注册ServiceB。通常,同一个服务提供商可以提供ServiceB,但其想法是使开发人员的总体接口更加简单,这样他们就不必提供多个服务接口(此外,ServiceB具有一些自动设置的属性,这些属性必须手动完成,并且可能无法正确完成).

我试图用一小部分测试包和ProSyst OSGi FW重新创建这个场景。 但是,如果我向DS注册了一个服务,则无法从activate()方法中注册其他服务。如果我只是使用DS获取服务,我可以像往常一样注册服务。所以DS/SCR可能真的有问题

例如:

public class ServiceAImpl implements ServiceA, ServiceB, ManagedService {

public void activate(ComponentContext _context) {
    _context.getBundleContext().registerService(
            ManagedService.class.getName(),
            this,
            null);
    _context.getBundleContext().registerService(
            ServiceB.class.getName(),
            this,
            null);
}


@Override
public void doA() {
    System.out.println("Doing A Stuff");

}


@Override
public void doB() {
    System.out.println("Doing B Stuff");
}


@Override
public void updated(Dictionary arg0) throws ConfigurationException {

}
} 此类将向该bnd注册2个服务(ServiceB、ManagedService)。文件:

Private-Package: org.test.impl
Service-Component: org.test.impl.ServiceAImpl
Bundle-Category: test
但此示例中只有1个服务(ServiceA):#


因此,您可能应该/必须尝试通过DS/SCR或通过bundle context的“经典方式”注册服务。

出现这种情况的原因是ServiceAImpl是一个已加载的延迟组件,因此ServiceA实际上在激活组件之前已重新注册。但是,当出现另一个需要ServiceA的组件时,这会导致ServiceAImpl被激活。ServiceAImpl激活过程的一部分是注册ServiceB,这将立即激活ServiceCImpl。对FELIX-2368进行了更改,通过使大多数SCR操作同步,立即激活组件


解决方法是使ServiceAImpl成为不需要的即时组件,因为如果没有任何东西需要该服务,则不应激活该组件。在这种情况下,激活方法在加载组件时完成,在需要它并将其绑定到另一个组件时没有问题。

您不能将ServiceB也注册为组件吗?
Private-Package: org.test.impl
Service-Component: org.test.impl.ServiceAImpl;provide:=org.test.ServiceA
Bundle-Category: test