我目前正在将一段代码从普通Java代码转换为OSGi Declarative Services。
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或服务概念。
首先,我将每个实现移动到自己的包中。然后我声明我的组件(服务实现)。我碰巧使用bnd,所以我使用服务注释。例如:
@Component
class ChildServiceImpl1 implements Service
在客户端类中,我们可以使用低级OSGi API查找服务,或者使用该包中的DS为我们创建对象。
查找“服务”的最佳方式是什么?我想要 AggregateServiceImpl,但我可能会收到一个ChildServiceImpls。
在查找ServiceReferences时,最好使用单独的服务类型或将属性添加到其中一个组件(例如“isRootService”)以用作过滤器吗?
答案 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构建聚合,因为它没有依赖于服务