3

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

我遇到了 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 的服务引用,将其称为 ServiceD。每次组件提供 ServiceD 接口时,都会使用相同的服务对象注册 ServiceB。通常同一个 ServiceD 的提供者可以提供 ServiceB,但想法是让开发人员的整体界面更加简单,这样他们就不必提供多个服务接口(此外,ServiceB 有一些属性是自动设置的,这些属性必须是手动完成,可能做错了)。

4

2 回答 2

2

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

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

于 2011-04-22T13:37:14.053 回答
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 或通过捆绑上下文的“经典方式”注册服务。

于 2011-04-21T12:19:09.783 回答