2

我目前正在将一段代码从纯 Java 代码转换为 OSGi 声明式服务。

原始纯 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 实现能够在调用时推迟到子 Service。

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

public class AggregateServiceImpl(Service... children)

澄清:接口名称“服务”是通用的,并不意味着代表 OSGi DS 或服务概念。

转换为 OSGi

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

@Component
class ChildServiceImpl1 implements Service

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

问题

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

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

4

2 回答 2

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;
于 2012-09-06T16:50:35.797 回答
1

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

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

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

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

于 2012-09-07T13:31:52.270 回答