我是OSGI的新手,我想了解如何注册服务?它总是通过 Activator
中的 BundleContext
对象?有替代方法吗?
假设我有一个接口 IService
,并且在同一个包中有两个实现 ServiceImpl1
和 ServiceImpl2
我正在注册它们,如下所示 .
context.registerService(IService.class.getName(), new ServiceImpl1(), props);
context.registerService(IService.class.getName(), new ServiceImpl2(), props);
但混淆是我如何具体要求特定的服务实施?
serviceImplObject = (IService) dictionaryServiceTracker.getService();</pre>
我不确定在这种情况下我会得到哪种实现方式 . 另外我没有看到任何选项来设置我需要什么类型的服务实现?
3 回答
有声明地注册和使用服务的替代方案 . 您可以使用Declarative Services (DS)或Blueprint Services . 还有其他一些,但这些都是实际规范的一部分 .
至于你目前正在使用的程序方法 . 您必须在注册时使用属性,并在创建跟踪器时使用过滤器 .
现在进行查找 .
(Updated with regards to ranking - thanks Neil) 如果没有过滤器,您将根据其排名和服务ID获得服务 . 如果您在动态环境中运行(这些服务正在停止并重新启动),则每次查找服务时都可以获得不同的实现 .
这是注册服务的简便方法 . 它使用声明性服务和bnd提供的注释:
现在,ServiceImpl类将被实例化并作为服务发布 . 对于使用服务,它看起来像这样(在最简单的情况下):
切勿使用激活剂 . 带有注释的DS组件(参见Neil的答案)是OSGi中的最佳实践 . 此外,DS不再需要服务跟踪器 . 如果我不得不再次使用OSGi,那么就没有激活器,没有服务跟踪器,只有DS .
现在关于服务选择 . 最糟糕的OSGi组件是想要聪明并选择特定实现的组件 . 如果你依赖于IService,那么你不应该关心你得到什么实现 . 如果您确实需要Impl1,请指定对Impl1的依赖关系 . 如果您尝试做出这些决定,则会使组件的可重用性显着降低 . 我通过删除这种代码显着提高公司可重用性的次数令人惊讶 .
DS中最酷的一个方面是它允许部署者(控制框中的人)决定应该将哪些服务绑定到谁 . 由于这些人对他们的世界有更多的了解,因此您作为开发人员会将其留给他们 .
用于控制DS中服务绑定的OSGi机制是通过Configuration Admin . 您可以为组件注册的服务设置引用(依赖项)和排名(或属性)的目标筛选器 . 因此,使用DS,这将成为可配置的决策 .
同样,我强烈建议终止所有这些选择代码,除非进行选择的信息实际上是您域的一部分 . 在这种情况下,获取所有服务,只需在绑定方法中过滤它们 .