osgi之ServiceListener的应用
2016-07-14 09:52
183 查看
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,执行命令之后如下所示:
发现这次进入断点的时候,event类型和上次有所不同,说明这里的ServiceListener的serviceChange方法对当前bundle启动的手,所有的服务注册都做了监听,这个时候,我们去掉断点,观察控制台,会发现打了许多次的’hello xiaxuan’,如下:
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的进一步封装,能够有效的监听我们所需的服务。
相关文章推荐
- 计算机程序的思维逻辑 (26) - 剖析包装类 (上)
- CDH5: 使用parcels配置lzo
- 不可小觑的吃内存大户
- saltstack安装配置笔记
- UVA-10878 Decode the tape
- oc与h5交互
- ArcGIS API for javascript开发笔记 —— 地图打印
- 常见的HTTP错误码的具体含义
- 集成框架jar包的一些选择
- 安卓 java有效判断Socket连接断开和安卓TCP测试APP(客户+服务端一体)
- Summer day 3
- Java--数组转成list,list转数组
- 个人记录--当前年月,求当月天数和上月
- .NET下为百度文本编辑器UEditor增加图片删除功能
- [bzoj十连测第五场 B]可持久化字符串
- [Tjoi2016&Heoi2016]【BZOJ 4553】【JZOJ 4606】序列
- jsp charset pageEncoding区别,中文乱码解决
- 跨平台之AppCan与DeviceOne对比点评记录
- 结构体sort快速排序
- mac os系统上 给mysql 5.7 安装和卸载