2012-12-20 144 views
3

我是OSGI的新手,我想了解如何注册服务?是否总是通过BundleContext对象在Activator?有没有其他可用的方法?注册服务并寻找服务

假设我有一个接口IService,并有两个实现ServiceImpl1ServiceImpl2在同一捆我正在注册他们如下。

context.registerService(IService.class.getName(), new ServiceImpl1(), props); 
context.registerService(IService.class.getName(), new ServiceImpl2(), props); 

但困惑是我该如何特别要求特定的服务实施?

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

我不知道在这种情况下我会得到哪个实现。另外我没有看到任何选项来设置我需要什么类型的服务实现?

+0

如果您使用的是过滤器,您将得到最适合您的过滤器的排名。否则,你会得到最高级别的实现 – Mirco

回答

5

声明式注册和使用服务还有其他选择。您可以使用Declarative Services (DS)Blueprint Services。还有其他的,但这些都是实际规范的一部分。

至于你正在使用的编程方法。创建跟踪器时,必须在注册时使用这些属性,并使用过滤器。

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); 

现在进行查找。

ServiceTracker primaryTracker = new ServiceTracker(bundleContext, "(&(objectClass=my.service.Service)(name=primary))", null); 
ServiceTracker secondaryTracker = new ServiceTracker(bundleContext, "(&(objectClass=my.service.Service)(name=secondary))", null); 

(与问候更新后排名 - 感谢尼尔) 没有过滤器,您将获得基于其排名和服务ID的服务。如果您在动态环境中运行(这些服务停止并重新启动),那么每次查找服务时都可能获得不同的实现。

+1

其实每次都不会有所不同;该选择是确定性的(第一过滤器;如果多个匹配则是最高排名;如果多个具有相同排名则是最低服务ID)。然而关键是服务使用者不应该关心它得到的服务实现。 –

+0

学习了一点之后.. org.osgi.framework包中的Constants类通过Constants.SERVICE_RANKING定义了service.ranking常量。该常量可用于设置服务排名的整数属性。如果有多个服务可用且有效,那么OSGi运行时将默认选择具有最低捆绑ID的服务。您还可以通过属性为您的服务设置服务排名。 OSGi默认分配零值作为服务排名,并选择排名最高的服务。 – Chetan

+0

@Neil - 更新以反映您的意见。然而,在动态环境中,决议将变得不太确定。完全同意,消费者不应该关心它得到的实现。简单地通过合同设计更简单。 – Robin

2

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

@Component 
public class ServiceImpl implements IService { 
    // ... 
} 

现在ServiceImpl类将被实例化并作为服务发布。对于消费服务,它看起来像这样(在最简单的情况下):

@Component 
public class ServiceImpl2 { 
    // ... 

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

谁是@Component和Reference注释的提供者?他们是OSGI的一部分吗? – Chetan

+0

不是它们是bnd的一部分,但它们只是构建时注释(不保留在.class文件中),因此它们不会将依赖关系添加到您的包中。 –

+1

有DS指定的DS 1.2注释。见http://www.osgi.org/javadoc/r4v43/cmpn/index.html?org/osgi/service/component/annotations/package-summary.html –

1

不要使用激活剂。带有注释的DS组件(请参阅Neil的答案)是OSGi中的最佳实践。此外,DS不再需要服务跟踪器。如果我必须再次执行OSGi,那么就不会有激活器,也没有服务跟踪器,只有DS。

现在关于服务选择。最糟糕的OSGi组件是想要变得聪明并选择特定实现的组件。如果你依赖于IService,那么你不应该关心你得到的实现。如果您确实需要Impl1,请指定Impl1的依赖关系。如果您尝试做出这些决定,则会使组件的重用性显着降低。我通过删除这种代码显着提高了公司的可重用性的次数令人惊讶。

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

控制DS中服务绑定的OSGi机制是通过配置管理。您可以为组件注册的服务设置引用(依赖关系)和排名(或属性)的目标过滤器。所以在DS中,这成为一个可配置的决定。

同样,我强烈建议杀死所有这个选择代码,除非所做的选择信息真的是你的域的一部分。在这种情况下,获取所有服务,并在绑定方法中过滤它们。