是否最好使用类型或属性在OSGi声明服务之间进行选择?

时间:2012-09-06 12:50:56

标签: java osgi declarative-services

我目前正在将一段代码从普通Java代码转换为OSGi Declarative Services。

原始普通Java代码

new AggregateServiceImpl(
    new ChildServiceImpl1(),
    new ChildServiceImpl2(),
    new ChildServiceImpl3()
);

这些类声明如下:

class AggregateServiceImpl implements Service
class ChildServiceImpl1 implements Service
class ChildServiceImpl2 implements Service
class ChildServiceImpl3 implements Service

所以所有类都实现了Service,但是Aggregate实现能够在被调用时推迟到子服务。

AggregateServiceImpl本身并不知道其他实现的存在。它的构造函数最初声明为:

public class AggregateServiceImpl(Service... children)

澄清:接口名称“服务”通常用于表示OSGi DS或服务概念。

转换为OSGi

首先,我将每个实现移动到自己的包中。然后我声明我的组件(服务实现)。我碰巧使用bnd,所以我使用服务注释。例如:

@Component
class ChildServiceImpl1 implements Service

在客户端类中,我们可以使用低级OSGi API查找服务,或者使用该包中的DS为我们创建对象。

问题

查找“服务”的最佳方式是什么?我想要 AggregateServiceImpl,但我可能会收到一个ChildServiceImpls。

在查找ServiceReferences时,最好使用单独的服务类型或将属性添加到其中一个组件(例如“isRootService”)以用作过滤器吗?

2 个答案:

答案 0 :(得分:3)

最好的方法是使用服务注册属性

 @Component
 @Service
 @Property(name = "service.id", value = "<some service unique ID")
 class ChildServiceImpl1 implements Service{...}

当您查找某些特定服务时,您可以使用服务过滤器:

bc.getServiceReferences(Service.class.getName(), "(service.id=<some value>)");

或者如果您想在DS组件中将其用作服务参考:

@Reference(target = "(service.id=<some value>)", cardinality = ...)
private Service service;

答案 1 :(得分:1)

如果 AggregateServiceImpl 是其他捆绑包使用的唯一服务,那么它应该是您注册的唯一 Service

从您当前显示的代码中,我们无法判断 AggregateServiceImpl 类是否依赖于 Service 或实际实现。

如果它直接依赖于其他实现,而不是 Service 接口(正如您当前所描述的那样),聚合包应该直接创建它需要的其他实现类,然后注册 AggregateServiceImpl 作为服务

如果其他实现也需要在其他地方使用,那么您应该使用属性(如您所建议的那样),以便消费者可以区分它们。在这种情况下,您仍然无法使用DS构建聚合,因为它没有依赖于服务