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通信过程。
时间: 2024-12-24 11:05:53

OSGI中Declarative Services的运用的相关文章

OSGI中的service依赖关系管理

众所周知,对于高动态高可扩展的应用,OSGI是一个非常好的平台.但是,也因此增加了复杂性,开发中对service的依赖变得复杂.这也是service的关系管理成为OSGI中一个非常重要的部分,我们来看看OSGI中service依赖关系管理的方式.篇幅原因,只关注发展历程,不具体介绍每个方式的详细实现细节. 概括的说,目前在OSGI中主要有以下几种service依赖关系管理的方法: 1. Service listener 2. Service binder 3. Dependency Manage

OSGI中ServiceTracker的应用

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

OSGi中的ServletContext

在OSGi中,不能的bundle分属不同的装载器(Class Loader), 在J2EE 应用中,不同BUNDLE 中的JSP 所对应的ServletContext对象不同,这与通常情况下的应用是不一样的. 一个例子如下: bundle a: [2014-07-22 11:08:21,335] SG-UAP : INFO Config:331 - --------------------------------------------------------- [2014-07-22 11:0

OSGI中自定义command(2)

OSGI中自定义command(2) 前文 在上一篇博文中,我们讲述了什么是OSGI中的command,同时写了一个简单的command,这个command实现了org.apache.felix.gogo.commands.Action这个接口,同样可以实现相同功能的还有 org.apache.karaf.shell.console.OsgiCommandSupport这一个抽象类,但是在本程序中,这两个接口或者抽象类上都标注了@Deprecated,因此已经不推荐使用了,而当前推荐使用的则是k

# OSGI中使用自定义的command

OSGI中command的应用 前文 在上一篇博文中,我们讲解了osgi中的blueprint,但并没有对此作出具体的运用,在本文及以后将会在讲osgi中其他应用的时候将blueprint串进来讲解,本文将要讲讲解的是osgi中的command,在编写的应用中,可能涉及到数据迁移或者其他一些操作,如果这个通过调用接口来进行操作的话,如果非相关人员获取到相关接口调用方式,可能会带来一些危害,所以在不得已的情况下不会使用接口的方式,这个时候command的作用就体现出来了,如果自己编写数个命令,然后

OSGI中blueprint简介

OSGI中blueprint简介 上篇博文我们开始了felix中的一个example编写,原本计划是讲felix中的几个example全部编写一遍,但是随后发现felix的这几个example都差不多,只是略微有些区别,编写来编写去始终都是这几行代码,讲起来也没什么意思,想着还是开始osgi中新的东西的讲解,思考来去,还是从blueprint开始. blueprint简介 在osgi中服务的使用有多种方式,如使用传统的注册式服务,就是我们之前中example不断使用的使用方式,还是osgi中的声

ofbiz,普通java程序,osgi中类加载

OSGI中类加载 在osgi中,存在多个类加载器,每一个类加载器加载一个独立的模块,当其他模块需要寻找这个类时,通过osgi框架依赖关系表去查找这个类所在的加载器,委托这个加载器去运行 ofbiz中类加载 ofbiz中集成了许多应用程序,像订单,安全,登陆,网店等,还有tomcat也被集成到ofbiz中,在ofbiz中是通过将这些应用程序的jar包和资源文件加载到同一个类加载器中(包括tomcat) 普通java程序 和ofbiz中类加载器一致

多个 ng-app 中 Controllers &amp; Services 之间的通信

原文发布在个人独立博客上,链接:http://pengisgood.github.io/2016/01/31/communication-between-multiple-angular-apps/ 通常情况下,在 Angular 的单页面应用中不同的 Controller 或者 Service 之间通信是一件非常容易的事情,因为 Angular 已经给我们提供了一些便利的方法:$on,$emit,$broadcast. 在这里用一个简单的例子来演示一下这三个方法的用途,完整版代码也可以参考这里

osgi中第三方bundle的问题

2015年1月20日写到: OSGi常见问题总结 :http://blog.csdn.net/ostrichmyself/article/details/7515653IBM的另一个场景:http://www-01.ibm.com/support/docview.wss?uid=swg21568564一个很多的文档:http://www.bouncycastle.org/specifications.html 头疼的问题:银联给了个jar包,upacp_sdk-1.0.0.jar 此包用于签名,