Java 注册服务并查找该服务

Java 注册服务并查找该服务,java,osgi,Java,Osgi,我是OSGI新手,我正在尝试了解如何注册服务?是否总是通过Activator中的BundleContext对象执行?有别的办法吗 假设我有一个接口iSeries设备,在同一个捆绑包中有两个实现ServiceImpl1和ServiceImpl2,我将它们注册如下 context.registerService(IService.class.getName(), new ServiceImpl1(), props); context.registerService(IService.class.ge

我是OSGI新手,我正在尝试了解如何注册服务?是否总是通过
Activator
中的
BundleContext
对象执行?有别的办法吗

假设我有一个接口
iSeries设备
,在同一个捆绑包中有两个实现
ServiceImpl1
ServiceImpl2
,我将它们注册如下

context.registerService(IService.class.getName(), new ServiceImpl1(), props);
context.registerService(IService.class.getName(), new ServiceImpl2(), props);
但令人困惑的是,我该如何具体要求特定的服务实现

serviceImplObject = (IService) dictionaryServiceTracker.getService();</pre>
serviceImplObject=(iSeries设备)dictionaryServiceTracker.getService();

我不确定在这种情况下我会得到哪种实现。我也看不到任何选项来设置我需要什么类型的服务实现

可以通过声明方式注册和使用服务。您可以使用或。还有其他的,但这些是实际规范的一部分

至于您目前使用的编程方法。注册时必须使用属性,创建跟踪器时必须使用过滤器

Map<String, String. prop1 = new HashMap<String, String>();
prop1.put("name", "primary");
context.registerService(IService.class.getName(), new ServiceImpl1(), prop1);

Map<String, String. prop2 = new HashMap<String, String>();
prop1.put("name", "secondary");
context.registerService(IService.class.getName(), new ServiceImpl2(), props);
(关于排名的更新-谢谢Neil)
如果没有过滤器,您将根据其排名和服务ID获得服务。如果您在动态环境中运行(这些服务正在停止并重新启动),则每次查找服务时都可能获得不同的实现。

以下是注册服务的简单方法。它使用声明性服务和bnd提供的注释:

@Component
public class ServiceImpl implements IService {
    // ...
}
现在,ServiceImpl类将被实例化并作为服务发布。对于使用服务,它如下所示(在最简单的情况下):


切勿使用活化剂。带有注释的DS组件(参见Neil的答案)是OSGi中迄今为止的最佳实践。此外,DS不再需要服务跟踪器。如果我必须再做一次OSGi,就不会有激活器、服务跟踪器,只有DS

现在谈谈服务选择。最糟糕的OSGi组件是那些希望变得聪明并选择特定实现的组件。如果您依赖IService,那么您不应该关心您得到了什么样的实现。如果确实需要Impl1,请指定对Impl1的依赖关系。如果您试图做出这些决定,那么您的组件的可重用性就会大大降低。我仅仅通过删除此类代码就显著提高了公司的可重用性,这是令人惊讶的

DS最酷的一个方面是它允许部署人员(控制盒子的人)决定哪些服务应该绑定到谁。因为这些人对他们的世界有更多的了解,所以作为一名开发人员,您可以将其留给他们

控制DS中服务绑定的OSGi机制是通过配置管理实现的。您可以为组件注册的服务的引用(依赖项)和排名(或属性)设置目标筛选器。因此,对于DS,这将成为一个可配置的决策


再次,我强烈建议删除所有这些选择代码,除非进行选择的信息确实是您域的一部分。在这种情况下,获取所有服务并在bind方法中对其进行筛选。

如果您使用的是符合您的筛选条件的最高级别的实现。否则,您将得到具有最高rankwho是@Component和引用注释的提供者的实现?它们是OSGI的一部分吗?不,它们是bnd的一部分,但它们只是构建时注释(不保留在.class文件中),因此它们不会向捆绑包添加依赖项。DS 1.2有DS指定的注释。其实每次都不会有什么不同;选择是确定的(第一个过滤器;如果多个匹配,则排名最高;如果多个具有相同排名,则排名最低的服务ID)。然而,关键的一点是,服务消费者不应该关心它得到了哪个服务实现。。org.osgi.framework包中的Constants类通过Constants.SERVICE_定义SERVICE.RANKING常量。此常量可用于设置服务排名的整数属性。如果有多个服务可用且有效,则OSGi运行时将默认选择具有最低捆绑ID的服务。您还可以通过属性为您的服务设置服务排名。OSGi默认为服务排名赋值为零,并选择排名最高的服务。@Neil-更新以反映您的评论。但在动态环境中,分辨率将变得不那么确定。完全同意消费者不应该关心它得到了哪个实现。简单地按合同设计要简单得多。
@Component
public class ServiceImpl implements IService {
    // ...
}
@Component
public class ServiceImpl2 {
    // ...

    @Reference
    public void setFoo(IService foo) {
        // ..
    }
}