OSGI中Declarative Services的运用

OSGI中Declarative Services的运用


前言

Declarative Services,即所谓的声明式服务,我在前文中曾经提及到注册式服务与声明式服务,但是在前文中并没有提及怎么使用声明式服务,只是简单的说了下概念和相对于blueprint来说有哪些优缺点,总而言之,可谓是一笔带过,这几日想起这个,还是决定需要仔细的讲一下声明式服务。


简介

Declarative Services,这是在OSGi 4以后的规范中出现的,在这里引用一段其他人说的话,Declarative Services 是一个面向服务的组件模型,它制订的目的是更方便地在 OSGi 服务平台上发布、查找、绑定服务,对服务进行动态管理,如监控服务状态以及解决服务之间的复杂的依赖关系等问题。Declarative Services 采用服务组件的延迟加载以及组件生命周期管理的方式来控制对于内存的占用以及启动的快速,很好的解决了传统的 OSGi 服务模型在开发和部署比较复杂应用时内存占用大、启动慢等问题,并且对服务组件的描述采用XML来实现,十分便于用户理解和使用。

以上几句话几乎可以在任何一段介绍osgi compendium都会提到,在我这也不免俗要提到几句,但是在此我更多的还是要介绍怎么使用而并不简单的讲解osgi compendium里面最新有哪些功能点,有哪些新的规范需要了解,我觉得这些只需要在官网中自己多去看几遍就可以了解,以下就是网址,IBM上的文章:

OSGi 中的 Declarative Services 规范简介

原版osgi compendium的规范为:

osgi compendium原文文档r4.cmpn.pdf

以上,对这些规范都讲得十分清楚,我在此不再赘述,仅仅是讲解在我使用Declarative Services发布一个服务之后,如何在另外一个Bundle中怎么使用这个服务,在此提一句,不要在编写Declarative Services的Bundle中使用该服务,会出现一些问题,这个在稍后会讲出来。


编写声明式服务

在使用Declarative Services的时候,要确保我们在pom文件中加了对compendium的支持,相关maven依赖
如下:

      <dependency>
        <groupId>org.osgi</groupId>
        <artifactId>org.osgi.compendium</artifactId>
        <version>${org.osgi.version}</version>
        <scope>provided</scope>
      </dependency>

我在这里编写了一个简单的程序,一个接口Test,提供一个hello方法,然后是一个实现类TestComponent,实现这个方法,具体以上的源码为:

Test:

package cn.com.ds;

/**
 * Created by xiaxuan on 16/7/13.
 */
public interface Test {

    String hello(String name);
}

TestComponet:

package cn.com.ds;

import org.osgi.service.component.ComponentContext;
import org.osgi.service.log.LogService;

/**
 * Created by xiaxuan on 16/7/13.
 */
public class TestComponent implements Test {

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

    public void activate(ComponentContext context) {
        System.out.println("activate(" + context + ")");
    }

    public void deactivate(ComponentContext context) {
        System.out.println("deactivate(" + context + ")");
    }

    public void modified(ComponentContext context) {
        System.out.println("modified(" + context + ")");
    }

    public void bind(LogService service) {
        service.log(LogService.LOG_INFO, "bind");
    }

    public void unbind(LogService service) {
        service.log(LogService.LOG_INFO, "unbind");
    }
}

这个里面active和deactive方法是用来监控在我们的服务在激活和钝化的时候使用的,在此处打出日志,说明组件被激活了,源码程序比较简单,现在来观察一下配置文件的编写,这个需要在resources目录下创建一个OSGI-INF的文件夹,然后创建文件components.xml,在xml中进行相关的配置,如下:

<?xml version = "1.0" encoding = "UTF-8"?>
<component name="TestComponent">
    <implementation class="cn.com.ds.TestComponent" />
    <service>
        <provide interface="cn.com.ds.Test"/>
    </service>
        <reference bind="bind" cardinality="1..1"
             interface="org.osgi.service.log.LogService" name="LogService"
             policy="dynamic" unbind="unbind" />
</component>

我在component中编写一个service,用以向外提供服务,同时还引用了LogService的服务,我们在实现的方法中,反复使用了LogService这个服务,在这里需要提一下的就是,我在这使用的是配置文件的形式来使用声明式服务,但是osgi还可以提供通过注解的方式来配置我们的组件,同样可以达到相同的效果,在上述完成之后,我们在当前Bundle之中要向外暴露这个服务,需要我们在felix的插件中加一行为如下:

<Service-Component>OSGI-INF/components.xml</Service-Component>

如此,在install完成后的Bundle中的mf文件之中,就会暴露这个服务。


使用声明式服务

使用这个服务相当简单,在feature配置文件中引入ds这个Bundle,然后在pom依赖中也加上ds的依赖,就可以使用ds这个Bundle提供的服务了,使用相当简单,我在Activator中编写的使用方法,和之前的ServiceTracker写在了一起,就是简单的使用context获取服务,然后使用,如下:

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


}

以上这个Activator和之前在ServiceTracker中编写的Activator没有任何区别,我把两个知识点的写到了一起,其中使用ds服务的代码就是在start中的最后两行。

ServiceReference serviceReference = bundleContext.getServiceReference(Test.class);
Test testComponent = (Test) bundleContext.getService(serviceReference);
System.out.println(testComponent.hello("bingwen"));

在使用上,没有任何区别。


程序运行

现在启动karaf,观察结果:
这里是图片描述
在这里可以看到我们正常使用Test服务,Test获取到了相应实例。在这里正常使用了ds。


总结

  • 相比于Declarative Services来说,个人还是更喜欢使用blueprint一些,毕竟相对于ds,blueprint更加方便。

  • 在ds声明中的Bundle中,不要在Activator中使用该服务,因为component的active的时间在Activator中的start方法之后,并且component的销毁时间也在stop方法之前,怎样都获取不到相应的实例,因此个人认为在一个Bundle中声明服务,在另外一个Bundle中引用最好不过。

  • 下一篇文章将讲解Bundle之间的EVentadmin通信过程。

本页内容版权归属为原作者,如有侵犯您的权益,请通知我们删除。
        我们都希望,配置文件是从一个服务引出,然后客户端监听服务端变化,实时重启自身加载最新配置,这样,我们就不用维护每个独立的客户端配置,更新也变得非常简单,而flume,显然意识到了这一个巨大的实惠,他是支持配置文件交由zookeeper维护的,这样我们在修改配置时,flume会自动重新加载。 1,zookeeper 添加节点         我们利用博客《 使用zkweb维护zookeeper数据 》中介绍的软件,编辑某一个随意路径,用于盛放我们的配置,路径如下: 2,flume 配置zk端
Spring MVC + mybatis实现的注册登录 前期准备:            如下图所示,准备好所需要的包, 新建工程,导入所需要的包,在web.xml中配置好所需要的,如下, ?xml version="1.0" encoding="UTF-8"?web-app version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance http://ww
工欲善其事,必先利其器。对于程序员来说,Eclipse便是其中的一个“器”。本文会从Eclipse快捷键和实用技巧这两个篇章展开介绍。Eclipse快捷键用熟后,不用鼠标,便可进行编程开发,避免鼠标分了你的神。而掌握了Eclipse的一些实用技巧,则可以大大提高开发效率。 1、丢掉鼠标吧之Eclipse快捷键篇 1.1文件切换的三种方式 1.1.1  Ctrl + E,在右边显示出当前打开的所有文件 1.1.2 Ctrl + Pg Up ,Ctrl + Pg Dn ,逐个文件跳跃 按下Ctrl + Pg
前言 想必HDFS集群的起停操作对于HDFS的使用者来说绝对不是一件陌生的事情.一般情况下我们重启集群服务是出于这2点原因:1).集群新增配置项,需要重启集群服务才能生效.2).对集群相关jar包程序进行了更新,需要重启服务来运行最新的jar包.于是我们重启了集群,一般的我们看它是否启动成功,一定会关注它的输出日志.比如说在HDFS中,我们会比较关注NameNode的启动日志.当然这的确是一个有效的办法,但是我们是否有其他更方便快捷的方法呢?比如说我不想登到NameNode所在节点上去看日志.最后的答案是
1、前言 进入 云计算 的时代,各大云提供商AWS, 阿里云 纷纷推出针对 Docker 的服务,现在Docker是十分火爆,那么Docker到底是什麽,让我们来体验一下。 2、Docker是什麽 Docker是一个开源的应用容器引擎,可以把应用以及依赖包放到一个可移植的容器中,然后发布到任何流行的  Linux  系统上,通过这种方式实现虚拟化。 提到虚拟化,大家应该十分熟悉了,有 VMware ,Xen, KVM 等等很多。那么,Docker和VM有什么不同呢,我们用官网的一张图来说明一下。 可以看出

MAT使用的几张图例技巧 - 2016-07-23 14:07:57

1 下面三个是内存泄漏可能性比较大的地方  problem suspect 1 problem suspect 2 点击detail 可以看详细  如果发现里面有自己工程包里面的重复的大量对象的创建 2 在dominator_tree 可以对象按照 group by package 分类 便于查看那部分代码出问题 如果自己的工程包下面占用了大量内存 可能就是问题所在 问题一般可能出在 占用最多的地方 3  选中一个节点 右键查看with incoming reference 可以看  ps :( List
重点发掘自己每天是否有学到或者感受到新东西,一旦可以感知这些细节,那么心态就会平和、也更容易坚持下来,自然而然就可以等到突破瓶颈的时候。 时间是一个很公平的东西,去体验不同的岗位去寻找自己真正想做的,是一个不错的思路。最怕的是目的性不明确的变化。 事实上那怕我们专注于一个领域,在某些时候还要跳出这个领域,开眼界后再回归方能更上一层楼。 ——祝晓春 手工测试二三事   @ 安琪儿的梦 o_0   提问:一直做手工测试会不会没有前 途 ? 任何一个工作和岗位都会有前途的,但是并不是每个人都会达到很大的高度。关

Spring+SpringMVC+Mybatis整合笔记 - 2016-07-22 22:07:05

出于兴趣,最近在研究SSM,参考着别人的技术资料并结合实际情况,一步一步的跑通了SSM整合的整个过程,现整理如下,希望对于同样对SSM有兴趣的你有所帮助,当然,因本人能力有限,可能有些问题,希望您能够指出来,咱们一起学习进步。   主要技术点: l  Spring + SpringMVC + Mybatis的整合 l  使用maven管理jar包及版本 l  使用mybatis generator代码生成器自动生成代码 l  使用SpringJUnit4ClassRunner进行单元测试   主要配置环境

DOS命令大全(经典收藏) - 2016-07-22 22:07:05

#1 一: net use \\ip\ipc$ " " /user:" " 建立IPC空链接 net use \\ip\ipc$ "密码" /user:"用户名" 建立IPC非空链接 net use h: \\ip\c$ "密码" /user:"用户名" 直接登陆后映射对方C:到本地为H: net use h: \\ip\c$ 登陆后映射对方C:到本地为H: net use \\ip\ipc$ /del 删除IPC链接 net use h: /del 删除映射对方到本地的为H:的映射 net user 用
原文地址:【 http://www.sciencedirect.com/science/article/pii/S0167865514001056 】 一、传统的Mean-Shift 原文地址:【 http://ieeexplore.ieee.org/xpls/abs_all.jsp?arnumber=1195991tag=1 】 个人理解(可能存在偏差,会不断改进): Mean-Shift算法用于tracking时,通过最小化两个概率密度函数之间的距离来进行,是一种 非参数技术 。 对于模板中的目标,即