我是 OSGi 新手,遇到过几个有关 OSGi 服务的示例。
例如:
import org.osgi.framework.*;
import org.osgi.service.log.*;
public class MyActivator implements BundleActivator {
public void start(BundleContext context) throws Exception {
ServiceReference logRef =
context.getServiceReference(LogService.class.getName());
}
}
我的问题是,你为什么使用
getServiceReference(LogService.class.getName())
而不是
getServiceReference("LogService")
如果您使用LogService.class.getName(),则必须导入接口(interface)。这也意味着您必须在 MANIFEST.MF 中导入包 org.osgi.services.log。
如果您想减少依赖关系以插入松散耦合,这不是完全适得其反吗?据我所知,服务的优点之一是服务使用者不必知道服务发布者。但如果您必须导入一个特定的接口(interface),您显然必须知道谁提供它。通过仅使用像“LogService”这样的字符串,您不必知道该接口(interface)是由org.osgi.services.log.LogService提供的。
我在这里缺少什么?
最佳答案
看起来您混淆了实现和接口(interface)
使用实际的接口(interface)作为名称(并导入接口(interface),无论如何你最终都会这样做)强化了服务设计所围绕的接口(interface)契约。您不关心 LogService 的实现,但您关心接口(interface)。每个 LogService 都需要实现相同的接口(interface),因此您可以使用该接口(interface)来获取服务。就您所知,LogService 实际上是由其他 bundle 提供的 SLF4J 的包装器。你看到的只是界面。这就是您正在寻找的松散耦合。您不必在每个实现中都附带接口(interface)。将接口(interface)保留为自己的包,并拥有该接口(interface)的多个实现。
旁注:ServiceTracker 通常更容易使用,请尝试一下!
额外的好处:使用接口(interface)获取类名可以避免拼写错误、过多的字符串文字,并使重构变得更加容易。
获得 ServiceReference 后,接下来的几行可能会涉及到以下内容:
Object logSvc = content.getService(logRef)
// What can you do with logSvc now?!? It's an object, mostly useless
// Cast to the interface ... YES! Now you need to import it!
LogSerivce logger = (LogService)logSvc;
logger.log(LogService.LOG_INFO, "Interfaces are a contract between implementation and consumer/user");
关于service - 如何正确使用 OSGi getServiceReference(),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2732456/