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

osgi之ServiceListener的应用

时间:2016-07-14 08:33:57      阅读:235      评论:0      收藏:0      [点我收藏+]

标签:

osgi之ServiceListener的应用


前言

我原想直接跳过这些osgi中基础知识,直接从osgi应用的一些中级篇或者高级篇开始的,后来想到osgi中的ServiceListener、ServiceTracker、Ds还是都需要讲一下,所以决定将osgicommand后续中的内容放一下,从ServiceListener开始讲一下,不过这里就不再讲述felix官网中的ServiceListener的example,而是自己单独编写example和进行相关讲解。


ServiceListener

/**
 * A {@code ServiceEvent} listener. {@code ServiceListener} is a
 * listener interface that may be implemented by a bundle developer. When a
 * {@code ServiceEvent} is fired, it is synchronously delivered to a
 * {@code ServiceListener}. The Framework may deliver
 * {@code ServiceEvent} objects to a {@code ServiceListener} out
 * of order and may concurrently call and/or reenter a
 * {@code ServiceListener}.
 * 
 */

ServiceListener解释如上所示,本义就是这只是一个接口,在进行相应的实现之后,可以用来监控某些服务,在服务注册、修改、注销的时候,进行相应的其他调用,现在我将讲述这个ServiceListener的具体使用,在使用过程中,再来讲解中间会有那些问题。


ServiceListener用法1

先分别提供一个接口和一个实现类,分别为HelloService和HelloServiceImpl,代码如下:

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;
    }
}

都很简单,就是提供一个简单的服务,其中有一个方法为hello,真正的重点还是在Activator中,现在先贴出Activator中的代码,随后再来讲解其中监听服务和容易出现的问题:

package cn.com.example;

import org.osgi.framework.*;

/**
 * Created by xiaxuan on 16/7/12.
 */
public class Activator2 implements BundleActivator, ServiceListener {

    ServiceRegistration serviceRegistration;
    BundleContext context;


    public void start(BundleContext context) throws Exception {
        this.context = context;
        context.addServiceListener(this);
        System.out.println("service registered....");
        serviceRegistration = context.registerService(HelloService.class, new HelloServiceImpl(), null);
    }

    public void stop(BundleContext context) throws Exception {
        context.removeServiceListener(this);
        System.out.println("service unregistered...");
        serviceRegistration.unregister();
    }

    public void serviceChanged(ServiceEvent event) {
        switch (event.getType()) {
            case ServiceEvent.REGISTERED:
                //获取service引用
                ServiceReference ref  = context.getServiceReference(HelloService.class);
                //获取service实例
                HelloService helloService = (HelloService) context.getService(ref);
                if (helloService != null) {
                    //调用service方法
                    System.out.println(helloService.hello("xiaxuan"));
                    //释放service
                    context.ungetService(ref);
                }
                break;
            case ServiceEvent.UNREGISTERING:
                System.out.println("serviceChanged find service unregistered.");
                break;
        }
    }
}

我们在Activator中实现ServiceListener之后,还需要将自己本身加入到监听器中,在serviceChanged方法中,当服务出现变化的时候可以在这个方法中监听到,其中或是注册,注销,或是修改都可以做出监听,现在我们打上断点,监听相关服务。


服务启动

服务启动过程就不再截图了,这次我们在stop bundle,然后再start bundle的时候再来调试和查看相应的信息,现在展示karaf已经成功启动的截图,如下所示:
技术分享
可以看到example这个Bundle已经正常启动,现在先使用stop命令,实质上在karaf中这个命令是Bundle:list命令,在karaf中大量的运用命令,在之后若有时间将会讲一下karaf的源码,讲一下这些命令,这个时候example的id为8,我们使用stop 8停止这个Bundle,执行命令之后如下所示:

技术分享

当Bundle中的state为resolved的时候,这个Bundle已经停止下来了,然后我们再启动Bundle,命令为start 8,这个时候我们观察我们的断点,这个断点设置在serviceChanged方法中,如下所示:

技术分享

我们放开断点,这个时候程序再次进入断点,如下:
技术分享

发现这次进入断点的时候,event类型和上次有所不同,说明这里的ServiceListener的serviceChange方法对当前bundle启动的手,所有的服务注册都做了监听,这个时候,我们去掉断点,观察控制台,会发现打了许多次的’hello xiaxuan’,如下:

技术分享

打了五次的hello xiaxuan,说明有五次的服务注册,每一次服务注册都进来获取了一次HelloService,然后调用了一次服务,在控制台打印一次,ServiceListener并没有对具体某个服务进行监听。


ServiceListener用法2

在以上ServiceListener的用法中,并不仅是在Activator中实现ServiceListener来做到监听服务,可以在start方法中直接实现,如果Activator类实现ServiceListener接口,还需要将本身加进Listener中,代码如下:

context.addServiceListener(this);

如果在start方法中实现的话,代码如下所示:

package cn.com.example;

import org.osgi.framework.*;

/**
 * Created by xiaxuan on 16/7/13.
 */
public class Activator3 implements BundleActivator {

    ServiceRegistration serviceRegistration;
    BundleContext context;


    public void start(BundleContext bundlecontext) throws Exception {
        this.context = bundlecontext;
        System.out.println("service registered....");
        serviceRegistration = context.registerService(HelloService.class, new HelloServiceImpl(), null);
        context.addServiceListener(new ServiceListener() {
            public void serviceChanged(ServiceEvent event) {
                switch (event.getType()) {
                    case ServiceEvent.REGISTERED:
                        //获取service引用
                        ServiceReference ref  = context.getServiceReference(HelloService.class);
                        //获取service实例
                        HelloService helloService = (HelloService) context.getService(ref);
                        if (helloService != null) {
                            //调用service方法
                            System.out.println(helloService.hello("xiaxuan"));
                            //释放service
                            context.ungetService(ref);
                        }
                        break;
                    case ServiceEvent.UNREGISTERING:
                        System.out.println("serviceChanged find service unregistered.");
                        break;
                }
            }
        });
    }

    public void stop(BundleContext context) throws Exception {
        System.out.println("service unregistered...");
        serviceRegistration.unregister();
    }
}

直接在addServiceListener中new ServiceListener,然后实现相关方法,相比较而言还简单一点,不过实现的效果相同。


总结

  • 使用ServiceListener时,只在Service发生相关变更的时候获取开销,可以动态感知service的注册和注销。

  • 但是问题在于在ServiceListener注册之前已经存在的Service无法监听到,需要自己维护service的获取和释放,如果需要监听多个service的话,十分不方便。

  • 只要是服务发生变更的时候就进行相关监听,其实在许多时候无需监听其他服务,有时候用起来比较麻烦。

  • 下一节中将讲解ServiceTracker,这是对ServiceListener的进一步封装,能够有效的监听我们所需的服务。

osgi之ServiceListener的应用

标签:

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

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