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

时间:2011-04-19 15:04:30

标签: osgi declarative-services

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

我遇到了Felix SCR的问题,我收到了消息:

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

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

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

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

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

没有尝试其他SCR实现,比如Equinox的版本,但我可能会尝试查看是否存在差异,但也许有人知道这是OSGi的东西还是Felix的东西?

附加信息:至于为什么ServiceB不是服务组件... ServiceA实际上有一个0..n的服务引用用于另一个服务,称之为ServiceD。每当组件提供ServiceD接口时,就使用相同的服务对象注册ServiceB。通常,ServiceD的同一提供者可以提供ServiceB,但其目的是使开发人员的整个界面更加简单,因此他们不必提供多个服务接口(同样,ServiceB有一些自动设置的属性,必须是手动完成,可能做错了。)

2 个答案:

答案 0 :(得分:2)

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

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

答案 1 :(得分:0)

我尝试用一​​小组测试包和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)使用此示例:#

Private-Package: org.test.impl
Service-Component: org.test.impl.ServiceAImpl;provide:=org.test.ServiceA
Bundle-Category: test

所以你可能/必须尝试通过DS / SCR或“经典方式”通过捆绑上下文来注册服务。