(02) Apache Felix 入门 - 02

1、说明

本文主要介绍如何创建一个最简单的 bundle?如何在 bundle 中监控服务的状态变化?如何配置 MANIFEST.MF 文件?如何编译、安装、运行我们打包好的 bundle,这并不一定需要是第一个例子,但是可以很好的帮助我们理解如何使用最简单的方式构建一个 bundle。

这个例子会详细的说明如何构建一个最简单的 bundle?如何编写相应的 manifest.mf 信息?如何编译、打包、安装

2、第一个例子

每一个 bundle 可以通过全局唯一的 BundleContext 实例和 OSGI 框架交互,那我们应该如何在一个 bundle 中获取该实例呢?答案是我们的 Bundle 必须要实现 BundleActivator 接口,该接口包含 void start(BundleContext context) 和 void stop(BundleContext context) 两个方法,在 bundle 被安装,并且启动的时候,start 方法会被调用,此时 BundleContext 实例会以参数的形式传递进来,同样当框架被停止的时候,stop 方法会被调用,此时 BundleContext 实例会以参数的形式传递给用户,除了实现了 BundleActicator 接口,下面的例子中还实现了 ServiceListener 接口,目的是将 Bundle 作为订阅者,监听自身的状态的改变,具体实现如下:

/*
 * Apache Felix OSGi tutorial.
**/

package tutorial.example1;

import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceListener;
import org.osgi.framework.ServiceEvent;

/**
 * 这里我们实现了 OSGI 的服务事件监听机制,即实现了 ServiceListener,
 * 在事件回调函数(ServiceChange)中,简单的输出了该事件的详细信息。
**/
public class Activator implements BundleActivator, ServiceListener
{
    /**
     * Implements BundleActivator.start(). Prints
     * a message and adds itself to the bundle context as a service
     * listener.
     * @param context the framework context for the bundle.
    **/
    public void start(BundleContext context)
    {
        System.out.println("Starting to listen for service events.");
        context.addServiceListener(this);
    }

    /**
     * Implements BundleActivator.stop(). Prints
     * a message and removes itself from the bundle context as a
     * service listener.
     * @param context the framework context for the bundle.
    **/
    public void stop(BundleContext context)
    {
        context.removeServiceListener(this);
        System.out.println("Stopped listening for service events.");

        // Note: It is not required that we remove the listener here,
        // since the framework will do it automatically anyway.
    }

    /**
     * Implements ServiceListener.serviceChanged().
     * Prints the details of any service event from the framework.
     * @param event the fired service event.
    **/
    public void serviceChanged(ServiceEvent event)
    {
        String[] objectClass = (String[])
            event.getServiceReference().getProperty("objectClass");

        if (event.getType() == ServiceEvent.REGISTERED)
        {
            System.out.println(
                "Ex1: Service of type " + objectClass[0] + " registered.");
        }
        else if (event.getType() == ServiceEvent.UNREGISTERING)
        {
            System.out.println(
                "Ex1: Service of type " + objectClass[0] + " unregistered.");
        }
        else if (event.getType() == ServiceEvent.MODIFIED)
        {
            System.out.println(
                "Ex1: Service of type " + objectClass[0] + " modified.");
        }
    }
}

以上类编写完成之后,我们还需要编写一个 manifest.mf 文件,这个文件的作用是声明 bundle 的一些列元信息,包括此 bundle 的名称、版本(重要)、创建者、启动入口(重要)、依赖的包(重要)、对外暴露的包(重要),具体如下:

Bundle-Name: Service listener example
Bundle-Description: A bundle that displays messages at startup and when service events occur
Bundle-Vendor: Apache Felix
Bundle-Version: 1.0.0
Bundle-Activator: tutorial.example1.Activator
Import-Package: org.osgi.framework // 必须以换行符结束(回车),否则此行将会被忽略。

Bundle-Name: Bundle 名称。

Bundle-Description: Bundle 的描述信息。

Bundle-Vendor: Bundle 的厂商信息,可能比较别扭,也就是这个 Bundle 是作者信息。

Bundle-Version: Bundle 的版本信息。

Bundle-Acticator: Bundle 的启动入口,当 Bundle 被安装之后,并且使用 Start 命令启动 Bundle 的时候,其指定的类会被自动构建,并且调用其实现的 BundleActivator 的 start 方法。

Import-Package: 声明此 Bundle 依赖的包,jre 标准提供的不需要声明。

Export-Package: 声明此 Bundle 中哪些包是对外暴露的,即允许其他 Bundle 使用。

接下来就是编译 Activator 类了,编译的时候,必须要保证 felix.jar 文件在类路径下,上述的文档中出现了中文,则需要在编译的时候指定源文件对应的编码格式,否则会编译出错,具体如下:

PS D:\devInstall\apache\felix-framework-6.0.0\examples\demo01\src> javac -cp ..\..\..\bin\felix.jar -encoding UTF-8 -d ../target .\tutorial\example1\*.java

上述的的命令如果看不明白的话,可以在命令行直接输入 javac,查看 javac 命令的使用帮助,这里我就不详细讲解了。

编译好 bundle 类之后,我们需要将编译好的类和 manifest.mf 一起打包为一个 jar 包,如下:

PS D:\devInstall\apache\felix-framework-6.0.0\examples\demo01\src> cd ../target
PS D:\devInstall\apache\felix-framework-6.0.0\examples\demo01\target> cp ../src/manifest.mf ./
PS D:\devInstall\apache\felix-framework-6.0.0\examples\demo01\target> jar cvfm example1.jar .\manifest.mf -C . .
已添加清单
正在添加: manifest.mf(输入 = 268) (输出 = 182)(压缩了 32%)
正在添加: tutorial/(输入 = 0) (输出 = 0)(存储了 0%)
正在添加: tutorial/example1/(输入 = 0) (输出 = 0)(存储了 0%)
正在添加: tutorial/example1/Activator.class(输入 = 1718) (输出 = 876)(压缩了 49%)

上述的的命令如果看不明白的话,可以在命令行直接输入 jar,查看 jar 命令的使用帮助,这里我就不详细讲解了。

打包完成之后我们将会得到一个名字为 example1.jar 的文件,然后再 felix 框架下安装此 bundle,具体命令如下:

Welcome to Apache Felix Gogo

g! install file:./examples/demo01/target/example1.jar
Bundle ID: 7
g! lb
START LEVEL 1
   ID|State      |Level|Name
    0|Active     |    0|System Bundle (6.0.0)|6.0.0
    1|Active     |    1|jansi (1.17.1)|1.17.1
    2|Active     |    1|JLine Bundle (3.7.0)|3.7.0
    3|Active     |    1|Apache Felix Bundle Repository (2.0.10)|2.0.10
    4|Active     |    1|Apache Felix Gogo Command (1.0.2)|1.0.2
    5|Active     |    1|Apache Felix Gogo JLine Shell (1.1.0)|1.1.0
    6|Active     |    1|Apache Felix Gogo Runtime (1.1.0)|1.1.0
    7|Installed  |    1|Service listener example (1.0.0)|1.0.0
g! start 7                                                                                                                                                                              
Starting to listen for service events. // bundle 启动输出信息

当上面的 bundle 被安装启动之后,框架中所有的服务注册、注销、更改事件都会被此 bundle 检测到,并且会打印出相应的事件信息,再后面的例子中我们将会讲解 OSGI 框架中服务如何构建、注册、使用。

猜你喜欢

转载自blog.csdn.net/Dreamcatcher_yxc/article/details/81413666
02