(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 框架中服務如何構建、註冊、使用。

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章