码迷,mamicode.com
首页 > 其他好文 > 详细

OSGI中ServiceTracker的应用

时间:2016-07-19 13:42:15      阅读:179      评论:0      收藏:0      [点我收藏+]

标签:

OSGI中ServiceTracker的应用


前文讲了ServiceListener,ServiceListener用于监听各种服务,但是如果要监听某一种服务的话,可能要花费一番功夫才能完成,但是我们可以使用osgi中另外一个监听服务的方式,就是ServiceTracker,这个在本质上是对ServiceListener的一种封装,对service的获取比ServiceListener比起来又简单许多,并且可以解决不能监听到已经存在的service的问题,先简单的看一下ServiceTracker的源码,然后在调试过程中再对具体进行讲解,部分源码如下:


    /**
     * Create a {@code ServiceTracker} on the specified class name.
     * 
     * <p>
     * Services registered under the specified class name will be tracked by
     * this {@code ServiceTracker}.
     * 
     * @param context The {@code BundleContext} against which the tracking is
     *        done.
     * @param clazz The class name of the services to be tracked.
     * @param customizer The customizer object to call when services are added,
     *        modified, or removed in this {@code ServiceTracker}. If customizer
     *        is {@code null}, then this {@code ServiceTracker} will be used as
     *        the {@code ServiceTrackerCustomizer} and this
     *        {@code ServiceTracker} will call the
     *        {@code ServiceTrackerCustomizer} methods on itself.
     */
    public ServiceTracker(final BundleContext context, final String clazz, final ServiceTrackerCustomizer<S, T> customizer) {
        this.context = context;
        this.trackReference = null;
        this.trackClass = clazz;
        this.customizer = (customizer == null) ? this : customizer;
        // we call clazz.toString to verify clazz is non-null!
        this.listenerFilter = "(" + Constants.OBJECTCLASS + "=" + clazz.toString() + ")";
        try {
            this.filter = context.createFilter(listenerFilter);
        } catch (InvalidSyntaxException e) {
            /*
             * we could only get this exception if the clazz argument was
             * malformed
             */
            IllegalArgumentException iae = new IllegalArgumentException("unexpected InvalidSyntaxException: " + e.getMessage());
            iae.initCause(e);
            throw iae;
        }
    }

在上述源码中可以看到在ServiceTracker的构造方法中,这一行代码确定了监听那个服务:

this.listenerFilter = "(" + Constants.OBJECTCLASS + "=" + clazz.toString() + ")";

下一行则创建了相应的监听器,并对服务进行了监听,如下:

this.filter = context.createFilter(listenerFilter);

在我们进行相应服务的使用的时候,在进行使用ServiceTracker的时候,这个时候就对相应的服务进行了监听,在稍后演示过程中再进行程序的调试的时候,再来对具体进行分析。


ServiceTracker源码

HelloService:

package cn.com.example;

/**
 * Created by xiaxuan on 16/7/12.
 */
public interface HelloService {

    String hello(String name);
}

HelloServiceImpl:

package cn.com.example;

/**
 * Created by xiaxuan on 16/7/12.
 */
public class HelloServiceImpl implements HelloService {

    public String hello(String name) {
        return "hello " + name;
    }
}

HelloServiceTracker:

package cn.com.example;

import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceReference;
import org.osgi.util.tracker.ServiceTracker;

/**
 * Created by xiaxuan on 16/7/12.
 */
public class HelloServiceTracker extends ServiceTracker {

    public HelloServiceTracker(BundleContext context) {
        super(context, HelloService.class, null);
    }

    @Override
    public Object addingService(ServiceReference reference) {
        System.out.println("adding service: " + reference.getBundle().getSymbolicName());
        return super.addingService(reference);
    }

    @Override
    public void removedService(ServiceReference reference, Object service) {
        System.out.println("removeing service: " + reference.getBundle().getSymbolicName());
        super.removedService(reference, service);
    }
}

Activator:

package cn.com.example;

import cn.com.ds.Test;
import cn.com.ds.TestComponent;
import org.osgi.framework.*;

/**
 * Created by Administrator on 2016/6/18.
 */
public class Activator implements BundleActivator {

    HelloServiceTracker serviceTracker;
    ServiceRegistration serviceRegistration;

    public void start(BundleContext bundleContext) throws Exception {
        System.out.println("service registered...");
        //开启服务跟踪器
        serviceTracker = new HelloServiceTracker(bundleContext);
        serviceTracker.open();
        //注册服务
        serviceRegistration = bundleContext.registerService(HelloService.class, new HelloServiceImpl(), null);
        //获取b被跟踪的服务
        HelloService helloService = (HelloService) serviceTracker.getService();
        if (helloService != null) {
            System.out.println(helloService.hello("xiaxuan"));
        }
        ServiceReference serviceReference = bundleContext.getServiceReference(Test.class);
        Test testComponent = (Test) bundleContext.getService(serviceReference);
        System.out.println(testComponent.hello("bingwen"));
    }

    public void stop(BundleContext bundleContext) throws Exception {
        System.out.println("Stopping service");
        //关闭服务跟踪器
        if (serviceTracker != null) {
            serviceTracker.close();
        }
        //注销服务
        serviceRegistration.unregister();
    }


}

演示

本次的演示还是和之前的一样,先启动bundle,然后再stop bundle后,再启动Bundle进入断点进行调试,查看断点时相关变量的状况,首先启动bundle,在karaf控制台中观察如下:
技术分享
id为10的bundle,example启动成功,dankaraf控制台中,可以看到还有id为18的一个Bundle在命名风格上与example差不多,这个将会是在后续中将要讲到的,到时候将会在ds中提供ds服务和在Bundle之间进行event通信,这个在这里暂且提一下,后续两篇博文将会讲到这些。

现在停止这个bundle,然后再次start,进入断点查看我们在ServiceTracker中大的断点的情况,如下所示:
技术分享
此时我将断点打到ServiceTracker中的构造方法中的listenerFilter的初始化处,此时观察listenerFilter监听的class,如下图:
技术分享
可以看到clazz就是我们先前传入的LogService,在随后创建的filter中,将会对这个filter进行监听,在程序中的ServiceTracker的对监听方法的获取中,如下图所示:
技术分享
获取服务的时候先从缓存中获取,然后cacheService为null,这里应该是在第一次中获取服务之后,边将对应service的引用存储在缓存中,随后在其后使用相应service的时候直接从cache中获取就可以了,没有从cache中拿到的时候,从getServiceReference()方法中获取,这个方法就不再讲解了,比较简单,就是首先cache中获取,如果获取到然后得到所有的ServiceReference后遍历,得到所需。


总结

  • 使用ServiceTracker使得获取Service的代码更加简洁和一致,不必再考虑Service是否存在的问题,并且ServiceTracker也提供了更加有效的监听Service的方式。

  • 有一点需要注意的是,tracker需要调用open方法才能监听到Service,另外,在bundle stop以后,bundle内open的ServiceTracker不会自动关闭,所以一定不要忘记在bundle结束之前,关闭所有在bundle中open的ServiceTracker。

  • 下一篇文章将开始讲解Declarative Services,即所谓的声明式服务。

OSGI中ServiceTracker的应用

标签:

原文地址:http://blog.csdn.net/u012734441/article/details/51953052

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!