我需要给定 OSGI 组件的多实例,即一些 bundle 将获得相同的实现实例,而其他 bundle 需要另一个实例。如果可能,我需要使用 XML 文件 而不是注释(如 @Component)。我使用的是混合 OSGI 4.3 平台,包含来自 eclipse 和 felix 的 bundle 。
比方说,我的服务界面是这样的:
public interface SocketService {
// Does nothing if already listening on given port
public void startListening(int port);
public String getNextMessage();
}
声明性 XML 文件如下所示并且工作正常:
<?xml version="1.0" encoding="UTF-8"?>
<scr:component xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0" name="SocketService">
<implementation class="declarativemultiton.service.impl.SocketServiceImpl"/>
<service>
<provide interface="declarativemultiton.service.SocketService"/>
</service>
</scr:component>
这些是消费者类,具有相同的语义:
public class Consumer1 {
public void activate() {
System.out.println("Consumer1 activated");
}
public void setSocketService(SocketService service) {
System.out.println("Consumer1 got SocketService@" + System.identityHashCode(service));
}
}
public class Consumer2 {
public void activate() {
System.out.println("Consumer2 activated");
}
public void setSocketService(SocketService service) {
System.out.println("Consumer2 got socketservice@" + System.identityHashCode(service));
}
}
以及它们的组件定义 XML:
<?xml version="1.0" encoding="UTF-8"?>
<scr:component xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0" name="Consumer1" immediate="true">
<implementation class="declarativemultiton.consumer1.Consumer1"/>
<reference bind="setSocketService" cardinality="1..1" interface="declarativemultiton.service.SocketService" name="SocketService" policy="static"/>
</scr:component>
<?xml version="1.0" encoding="UTF-8"?>
<scr:component xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0" name="Consumer2" immediate="true">
<implementation class="declarativemultiton.consumer2.Consumer2"/>
<reference bind="setSocketService" cardinality="1..1" interface="declarativemultiton.service.SocketService" name="SocketService" policy="static"/>
</scr:component>
一切都按预期工作,并且两个组件都获得相同的实例:
Socket Service Impl activated
Consumer1 got SocketService@1769618707
Consumer1 activated
Consumer2 got socketservice@1769618707
Consumer2 activated
我需要 Component1 和 Component2 获取不同 SocketService 实例,并且 Component2 和 Component3(未显示)具有相同 SocketService 实例。
如果我将配置策略更改为“要求”,则不会激活消费者组件:
<?xml version="1.0" encoding="UTF-8"?>
<scr:component xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0" configuration-policy="require" name="SocketService">
<implementation class="declarativemultiton.service.impl.SocketServiceImpl"/>
<service>
<provide interface="declarativemultiton.service.SocketService"/>
</service>
</scr:component>
这是我迷路的地方,我不知道如何将配置动态传递给 SocketService。在阅读有关 ConfigurationAdmin、ManagedService、ManagedServiceFactory、ComponentFactory 等内容时,我一直在纠结。我找不到一个具体、简洁的解决方案。有一些相互矛盾的方法,比如这个答案 https://stackoverflow.com/a/4129464/330464说不要使用 ManagedService,而是使用 Karaf 教程 http://sully6768.blogspot.com.tr/2012/09/declarative-services-with-karaf-part-4.html解决了它的使用问题。
最佳答案
我认为您使用服务属性来识别或区分使用组件上的 SocketFactory 实例和目标属性以确定使用哪一个是正确的方法,但我建议使用配置而不是每个实现使用多个组件 xml类(class)。我不太清楚您有多少个 SocketFactory 或消费者的实现类。为了说明,我将假设每个人都有一个。
您可以通过 config admin 使用 DS 组件的配置,而不是复制组件 xml 并在那里修改属性。 Peter Kriens 在此处对 DS 包括配置进行了很好的解释: http://enroute.osgi.org/services/org.osgi.service.component.html .以下是一些更详细地涵盖使用配置设置引用的步骤:
将配置 pid 添加到您的组件 xml。让我们假设 socketFactory 为 socketFactory,消费者为 consumer。
安装配置管理员。我觉得 felix 和 eclipse 都很好,我只用过 felix。
在您想要安排套接字工厂启动的包中,执行一些获取 ConfigAdmin 实例的代码并调用类似
Configuration sfc = ca.createFactoryConfiguration("socketFactory", null); Hashtable<String, Object> props = new Hashtable<String, Object>(); props.put("socketType", "MyType"); sfc.update(props);
如果此代码与 SocketFactory 代码捆绑在一起,您可以省略 null 参数。 这将生成一个带有 socketType=MyType 服务属性的 SocketFactory 组件,类似于您对组件属性所做的操作。
在要安排消费者设置的 bundle 中,执行类似的操作但使用目标过滤器:
Configuration cc = ca.createFactoryConfiguration("consumer", null); Hashtable<String, Object> props = new Hashtable<String, Object>(); props.put("SocketService.target", "(socketType=MyType)"); cc.update(props);
这将生成具有指定目标过滤器的消费者组件。
您也许可以选择使用例如felix fileinstall 从属性文件安装配置。这是非常声明性的,但我没有任何经验,而且我看到有些人很难将所有部分排成一行,因此它可以工作。在工作中,我有幸使用了一个基于 xml 的系统:它从元类型生成一个模式,并将 xml 配置文档(符合生成的模式)与元类型结合以生成配置。它可以从例如生成目标过滤器元素。嵌套的 xml。我经常希望有一个开源版本。
顺便说一句,您可能想重新审视您对 spec ds 注释的回避。它们不在运行时使用,而是在您组装包时由 bnd 处理。 (您正在使用 bnd,不是吗?)。 Bnd 将为与您的组件兼容的尽可能低的 ds 版本生成 component.xml,并且它会比您手动执行更多的验证(至少比我手动执行的要多)。
关于java - 带有组件 XML 文件的 OSGI DeclarativeService Multiton,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33171587/