Java 处理动态OSGi服务依赖关系的最佳方法

Java 处理动态OSGi服务依赖关系的最佳方法,java,osgi,declarative-services,Java,Osgi,Declarative Services,我有一个可选的服务依赖项,如下所示: @Component class TestComponent { private AtomicReference<TestService> testServiceRef; @Reference(type = '?') protected void setTestService(TestService testService) { testServiceRef.set(testService); } protected

我有一个可选的服务依赖项,如下所示:

@Component
class TestComponent {
  private AtomicReference<TestService> testServiceRef;

  @Reference(type = '?')
  protected void setTestService(TestService testService) {
    testServiceRef.set(testService);
  }
  protected void unsetTestService(TestService testService) {
    testServiceRef.set(null);
  }

  public void doStuff() {
    TestService testService = testServiceRef.get();
    if (testService != null)
      testService.performSomeTask();
  }
}
@组件
类TestComponent{
私有原子引用testServiceRef;
@引用(类型=“?”)
受保护的void setTestService(TestService TestService){
testServiceRef.set(testService);
}
受保护的测试服务(TestService TestService){
testServiceRef.set(空);
}
公共空间{
TestService TestService=testServiceRef.get();
if(testService!=null)
testService.performsMetask();
}
}

现在,如果在testService.performSomeTask()运行时服务被解除绑定,那么我有一个问题,对吗?我是否需要在所有这些函数中添加同步块,或者是否有更好的方法来处理这种情况?

您不需要使用同步和原子引用。我通常建议对具有动态策略的DS引用使用原子引用

话虽如此,您的代码存在两个问题:

  • testServiceRef
    字段从未初始化。您应该在构建过程中对其进行初始化,理想情况下将其设置为
    final
  • unsetTestService
    的实现不正确。在动态服务替换期间,“新”服务的绑定发生在“旧”服务解除绑定之前。因此,您需要检查正在解除绑定的服务是否就是您当前绑定的服务。您可以通过调用
    testServiceRef.compareAndSet(testService,null)
    来实现这一点

  • 我认为没有答案,因为您在示例中提供了最著名的方法(使用原子引用)。由于AtomicReference内部使用volatile变量,我认为在不久的将来有必要检查支持Intel TSX-NI的最新Intel CPU上的volatile或同步块是否更快。Java 1.8.0_25支持使用短同步块的TSX-NI,但我不确定是否可以使用易失性变量实现相同的性能改进。为什么您认为除了使用AtomicReference之外还需要进行同步?@Balazsoldos AtomicReference不是简单地使用易失性变量实现的;它使用本机CAS指令。无论如何,性能根本不是问题所在。。。服务发布每秒发生多少次?@NeilBartlett AtomicReference类中的值成员变量不稳定。get和set函数直接使用这个变量,我不知道Java8的TSX-NI实现是否可以增强对易失性变量的访问。compareAndSet、lazySet和其他函数使用不安全类(至少在OpenJDK中是这样)。谢谢Neil。如果在performSomeTask()运行时卸载了包含TestService实现的捆绑包,是否会出现问题?不太可能。服务调用可能会引发异常,但作为服务的使用者,您应该始终准备好让该服务不可靠。