OSGi:将服务重构为声明性服务

时间:2013-01-14 09:53:50

标签: java spring osgi apache-felix eclipse-virgo

我正在与OSGi取得联系,现在我有点困惑。我使用的是混合服务模型,意思是声明性服务和低级API的混合。

考虑在OSGi-INF / component.xml下放置的以下部分声明:

<property name="canHandle" type="String" value="Some kind of stuff"/>
<service>
  <provide interface="foo"/>
</service>

和另一个

<property name="canHandle" type="String" value="Some other Stuff"/>
<service>
  <provide interface="foo"/>
</service>

在另一个包中我有这样的东西:

bar.createSomething(String type){

ServiceReference[] services FrameworkUtil.getBundle(getClass()).getBundleContext()
                .getAllServiceReferences("foo");
for (ServiceReference s : services) {
    if (type.equals(s.getProperty("canHandle")){
        Foo foo = (Foo)FrameworkUtilgetBundle(getClass()).getBundleContext().getService(s);
foo.execute();

总而言之,我有一个具有多个实现的服务接口,并且在运行时我使用的是匹配属性的字符串。那么我怎样才能使用声明性服务处理这种情况呢?

我们正在使用处女座,所以如果春天有可能,这也是一个选择。

1 个答案:

答案 0 :(得分:4)

您可以使用<reference>元素上的目标过滤器执行此操作。或者,使用bnd注释:

@Reference(target = "(canHandle=blah)")
public void setFoo(Foo foo) {
    // ...
}

现在,即使有多个Foo服务实例可用,也只会将与过滤器(canHandle=blah)匹配的服务实例注入您的组件。

<强>更新

有人澄清说,要匹配的值不是静态知道的。在这种情况下,不能使用静态过滤器。但您仍然可以使用声明性服务并手动检查服务属性的值,例如:

@Reference(multiple = true, dynamic = true)
public void setFoo(Foo foo, Map<String,Object> serviceProps) {
    if ("value".equals(serviceProps.get("canHandle"))) {
        // ...
    }
}

请记住,您现在可能会获得多个匹配的实例。