当存在多个实现时,优先考虑容器内的OSGi服务选择

时间:2009-12-05 02:50:14

标签: osgi

我正在玩OSGi并且有一些捆绑。 Bundle A和B都包含一个实现单个接口的注册服务。第三捆绑包C包括用于查找实现前述接口的服务的代码。 A和B捆绑包具有不同的版本号,但是看起来C从第一个启动的捆绑包中获取服务。我已经更改了启动级别以执行正确的操作,但版本仅用于接受而不是订购返回的服务。

   A version 1.0 start level 1
   B version 1.1 start level 2
   C requires both bundles, start level 3

在上面的示例中,C总是从A获取服务,即使B具有更高的捆绑版本。但是,如果我切换启动级别,那么B在A之前启动,C看到B服务。

我搜索过OSGi网站,并没有明确解释是否使用捆绑版本来优先考虑服务而不是另一个服务。我的理解似乎表明,启动级别应该用于命令bundle启动,以便正确地满足依赖性。但是它似乎过载,因此它也优先考虑服务优先级。考虑到上述所有情况,我想在选择中不使用捆绑版本是有道理的,因为版本号只是一个相对于任何数字的数字。

除了启动级别之外,将一项服务优先于另一项服务的最佳方法是什么?

3 个答案:

答案 0 :(得分:19)

确定OSGi服务优先级以使用SERVICE_RANKING服务属性的最佳方法。可以在传递给的properties对象中提供此属性 BundleContext.registerService()方法。

根据BundleContext.getServiceReference()方法的文档:

  

如果存在多个此类服务,则返回排名最高的服务(在其Constants.SERVICE_RANKING属性中指定)。

     

如果排名有关系,则服务ID最低的服务(在Constants.SERVICE_ID属性中指定);也就是说,返回首先注册的服务。

答案 1 :(得分:3)

如果服务是由第三方库注册的,您可能无法控制其排名或注册属性。使用ServiceTracker可以让您获得更多控制权。 例如,您可以执行以下操作:

ServiceTracker tracker = new ServiceTracker (bundleContext, serviceClass ,new ServiceTrackerCustomizer () {

            @Override
            public Object addingService(ServiceReference srvRef) {

                boolean criteria =  // whatever your criteria is for prioritizing
                        if(criteria)
                            return bundleContext.getService(srvRef);
                        else
                            return null;
            }

            @Override
            public void modifiedService(ServiceReference srvRef, Object arg1) {


            }

            @Override
            public void removedService(ServiceReference srvRef, Object arg1) {

            }

        });
tracker.open();
Object service = tracker.getService();

答案 2 :(得分:1)

org.osgi.framework.BundleContext.registerService(String[], Object, Dictionary)中,您可以在Dictionary中指定任意属性。要查找服务,您可以在org.osgi.framework.BundleContext.getServiceReferences(String, String)中指定过滤器。如果这还不够,您可以检查org.osgi.framework.ServiceReference.getProperty(String),例如优先级值。