在OSGi中,传递服务引用是一种好的做法还是应该捆绑自己查找?

时间:2013-03-08 15:37:14

标签: java service osgi bundle blueprint-osgi

我有这些捆绑包:

  • 通讯服务提供通讯服务。
  • 通信是使用Comm Service发送/接收邮件的通讯捆绑包。
  • 轮询以组播方式发送轮询消息。

Communication捆绑包已经饱和,我的方法是为特定操作实现其他捆绑包 - 民意调查捆绑包将负责发送民意调查,明信片用于发送明信片等的捆绑包(仅举几例)。

Comm Service捆绑包需要委派发送民意调查/明信片/消息的工作时,是否将Poll服务作为Communication捆绑包的输入参数传递?

下面的代码段是否正确?

通讯捆绑代码

PollBundle p = new PollBundleImpl();
p.sendPoll(String pollQuestion, CommService cs);

或者让Poll / Postcard捆绑包自行检索Comm Service服务是更好的方法吗?

3 个答案:

答案 0 :(得分:8)

不得在捆绑包之间传递服务对象;如果你这样做,那么OSGi框架将失去对哪些捆绑包具有服务可见性的控制权,因此当该服务需要消失时,它无法通知整套捆绑包。

因此,Poll包必须为自己找到CommService。有很多方法可以做到这一点。我强烈建议使用OSGi规范中的声明性服务。与bnd annotations结合使用,您将能够编写Poll包的代码,如下所示:

@Component
public class Polling {

    private CommService commService;

    @Reference
    public void setCommService(CommService cs) {
        this.commService = cs;
    }

    public void someMethodThatUsesCommService() {
         sendPoll(cs);
         // ...
    }
}

我推荐这种方法优于Jacek Laskowski在其答案中描述的蓝图解决方案,因为它不需要编写详细和非类型安全的XML文件,并且它具有与OSGi服务生命周期相匹配的更好的生命周期特征。然而,声明式服务和蓝图方法肯定比使用低级OSGi API(例如ServiceTrackerServiceListener)更安全。

答案 1 :(得分:2)

我强烈建议使用OSGi Blueprint的{​​{3}}分离捆绑包(请参阅dependency injection中的蓝图容器规范,但请注意它是否适用于V5版本)。

根据规范,您使用单独的xml文件声明捆绑包的依赖关系 - OSGI-INF/blueprint/*.xml(默认值,但可以使用Bundle-Blueprint标头进行更改。)

因此,在您的情况下,您将开发Comm Service捆绑包,其服务是Communication捆绑包的依赖关系。还有Poll和可能Postcard捆绑的相同服务接口注册服务,以便它们可以成为Communication捆绑包的依赖项。

在此类配置中,Communication捆绑包/服务不是Comm Service捆绑包,但在初始化期间,PollPostcard捆绑包会获得Comm Service捆绑包服务依赖。

以下是Poll捆绑包的假设蓝图配置。

<?xml version="1.0" encoding="UTF-8"?>
<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0">
  <bean id="PollSenderBean" class="pl.japila.osgi.poll.PollSender">
    <argument ref="commService" />
  </bean>
  <service id="PollSenderBeanService" ref="PollSenderBean" 
           interface="pl.japila.osgi.Sender">
    <service-properties>
      <entry key="type" value="poll" />
    </service-properties>
  </service>
  <reference id="commService" interface="pl.japila.osgi.comm.CommService" />
</blueprint>

Postcard捆绑包类似。请注意entry,其值为poll,以便在需要此类查询时获取特定服务。

Communication捆绑包的蓝图配置如下:

<?xml version="1.0" encoding="UTF-8"?>
<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0">
  <reference-list activation="lazy" member-type="service-object"
                  id="Sender" interface="pl.japila.osgi.Sender" />
</blueprint>

请参阅规范,或许OSGi Service Platform Enterprise Specification来学习和学习解决方案。

答案 2 :(得分:1)

除非您需要在CommService的{​​{1}}的不同调用中使用其他p.sendPoll(String pollQuestion..),否则请PollBundle自行查找CommService

基本上这会减少耦合。您只需要了解PollBundle即可发送投票。这实际上取决于您的体系结构,但一般来说,移动所需的对象越少,接口越简单越好。