【发布时间】:2019-05-08 05:41:15
【问题描述】:
我有一个需要配置的服务
@Component(service=InstrumenterService.class ,configurationPid = "InstrumenterService", configurationPolicy = ConfigurationPolicy.REQUIRE, scope = ServiceScope.PROTOTYPE)
public class InstrumenterService
该服务在另一个服务中被引用:
@Component(service = SampleService.class, scope = ServiceScope.PROTOTYPE)
public class SampleService {
@Reference(cardinality = ReferenceCardinality.OPTIONAL, scope = ReferenceScope.PROTOTYPE_REQUIRED, policyOption = ReferencePolicyOption.GREEDY)
InstrumenterService coverageInstrumenter;
public boolean hasInstrumenter() {
if(coverageInstrumenter == null)
return false;
return true;
}
}
此 SampleService 用于与主 osgi 线程挂钩的 Main 类中。 我正在使用 ComponentServiceObjects,因为我想按需创建 SampleServices。
@Component(immediate = true, property = "main.thread=true")
public class Main implements Runnable {
@Reference
ConfigurationAdmin cfgAdm;
@Reference(scope = ReferenceScope.PROTOTYPE_REQUIRED)
private ComponentServiceObjects<SampleService> sampleServices;
public void run() {
if (cfgAdm != null) {
Configuration configuration;
try {
configuration = cfgAdm.getConfiguration("InstrumenterService", "?");
Hashtable<String, Object> props = new Hashtable<>();
props.put("some_prop", "some_value");
configuration.update(props);
} catch (IOException e1) {
e1.printStackTrace();
}
}
SampleService servicess = sampleServices.getService();
System.out.println(servicess.hasInstrumenter());
}
}
我遇到的问题是 ConfigurationAdmin 设置的配置在 InstrumenterService 中不可见,除非我放一个 Thread.sleep(500);调用 configuration.update 后的命令。
我不太习惯使用 Thread.sleep 命令来确保配置更新可见。 是否有 API 可以检查配置是否已更新并可使用?
感谢 Neil,我能够找到一个可行的解决方案。 在配置设置为等待服务后,我使用了 ServiceTracker:
BundleContext bundleContext = FrameworkUtil.getBundle(getClass()).getBundleContext();
ServiceTracker serviceTracker = new ServiceTracker(bundleContext, InstrumenterService.class.getName(), null);
serviceTracker.open();
try {
serviceTracker.waitForService(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
serviceTracker.close();
我首先需要 ConfigurationAdmin 的原因是因为有一个接口 IInstrumenter 可以由许多不同的类实现。 该仪器的名称在 ConfigurationAdmin 中设置,然后在其他服务中进一步“自动”获取所需的仪器服务。
这样可以将任意数量的仪器添加到应用程序中,并且只需要知道仪器的名称才能使用它。
我还想提一下,通过 OSGI,我们设法将我们的单体遗留应用程序拆分为更多模块(约 15 个),它们不直接相互依赖,而是使用 API 层。
再次感谢您使用 OSGI 所做的出色工作。
【问题讨论】:
-
您能解释一下为什么需要等待配置更新吗?
-
如果我不等待配置更新,我将在 SampleService 类中获得 InstrumenterService coverageInstrumenter 的空引用(因为 ConfigurationPolicy.REQUIRE)。如果我等待,那么covergeInstrumenter 服务不再为空。
-
抱歉,我的问题措辞有误。为什么需要在设置配置的相同方法中获取服务的实例?
-
我不一定需要用同样的方法。这是一个捕获问题的简化示例。我是真正的应用程序,我不会从同一个方法调用它们,但我确实有一个 main 方法挂在 main.thread=true" 上。在实际应用程序中,这个问题偶尔会发生,因为在设置配置之间完成了更多的处理并创建需要配置的服务。