这是另一个问题的副本,但是从另一个问题复制:
我遇到了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有一些自动设置的属性,必须是手动完成,可能做错了。)
答案 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或“经典方式”通过捆绑上下文来注册服务。