我有一项需要配置的服务
@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());
}
}
我遇到的问题是,除非我放置Thread.sleep(500),否则在InstrumenterService中看不到ConfigurationAdmin设置的配置。调用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所做的出色工作。
答案 0 :(得分:0)
正如注释中所阐明的,此代码并不完全现实。在生产代码中,通常不需要更新配置记录,然后立即获取组件发布的服务。这是因为任何此类代码都对配置更新的效果做出了太多假设。
对getServiceReference
和getService
的调用仅在特定时刻返回服务注册表状态的快照。调用getService
期望它返回一个值本质上是不可靠的。
实际上,我们总是使用一种模式,在这种情况下,我们会响应通知服务存在的情况。这可以通过多种方式完成,包括ServiceListener
和ServiceTracker
,但是最简单的方法是编写一个带有引用的组件,例如:
@Component
public class MyComponent {
@Reference
SampleService service;
public void doSomething() {
println(service.hasInstrumenter());
}
}
此组件具有对SampleService
的强制性引用,并且仅在SampleService
的实例可用时才会激活。