Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> osgi之Eventadmin通信

osgi之Eventadmin通信

編輯:關於Android編程

osgi中bundle之間的通信,可以使用eventadmin來完成,eventadmin是osgi中的一種基於發布訂閱的方式,一個Bundle進行發布發布一個事件之後,另外一個Bundle訂閱相應主題,從而進行通信,在使用過相同的通信方式中,guava中有一個eventbus可以達到相同的效果,以及mq的發布訂閱均是如此,但是osgi的eventadmin服務,在通信過程中event事件不是持久化的,現在開始我們的osgi之間的event事件通信。


發布事件

我們在擬定事件的主題之後可以進行相應事件的發布,這使用的還是compedium中的Eventadmin服務,如同上一篇文章中引入的依賴一樣,需要使用到compedium這個包,發布事件相當簡單,獲取到Eventadmin之後就可以進行相應的事件發布,但同時要指定topic,指定主題之後,訂閱者才能根據相應的主題獲取到訂閱事件。發布事件的代碼相當簡單,如下所示:

package cn.com.ds;

import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceReference;
import org.osgi.service.event.Event;
import org.osgi.service.event.EventAdmin;
import org.osgi.service.event.EventConstants;

import java.util.HashMap;

/**
 * Created by xiaxuan on 16/7/11.
 */
public class Activator implements BundleActivator {

    private BundleContext context;

    boolean flag = true;

    private ServiceReference sr;

    EventAdmin eventAdmin = null;

    HashMap properties = null;

    Event event = null;

    public void start(BundleContext context) throws Exception {
        this.context = context;
        sr = context.getServiceReference(EventAdmin.class.getName());
        if (sr == null) {
            throw new Exception("Failed to obtain EventAdmin service reference!");
        }
        eventAdmin = (EventAdmin) context.getService(sr);
        if (eventAdmin == null) {
            throw new Exception("Failed to obtain EventAdmin service object!");
        }
        while (flag) {
            if (eventAdmin != null) {
                properties = new HashMap();
                properties.put(EventConstants.BUNDLE_SYMBOLICNAME, "est.first");
                //create event topic
                event = new Event("my_osgi_test_event", properties);
                eventAdmin.postEvent(event);        //asynchronous
                System.out.println("Send Event!");
                try {
                    Thread.sleep(5000);
                } catch (Exception e) {}

            }
        }
        System.out.println("ds service registered..");
    }

    public void stop(BundleContext context) throws Exception {
        //flag = false;
        System.out.println("service stoping...");
    }
}

在獲取到EventAdmin服務諸侯就可以進行事件發布了,其中我指定的Event的topic為my_osgi_test,在進行Event初始化的時候指定topic,我在發布事件的時候我使用的是postEvent,這是一種異步發送事件的方式,有一種同步的事件發送為sendEvent,兩者的區別在於,異步發送無論是監聽者是否接收成功都會返回,而同步發送則是會等到監聽者接收成功才會返回,所以在這裡會出現一個問題,就是當監聽的Bundle沒有啟動起來,或者stop之後,當前發送Event的Bundle暫時也會阻塞起來,造成其他的問題。

EventHandler

在Event訂閱者中需要一個EventHandler來處理相應Event,這個EventHandler需要實現EventHandler接口,實現一個handler方法,我在這寫了一個簡單的EventHandler為以下:

package cn.com.event.handler;

import org.osgi.service.event.Event;
import org.osgi.service.event.EventHandler;

/**
 * Created by xiaxuan on 16/7/15.
 */
public class MyEventHandler implements EventHandler {

    public void handleEvent(Event event) {
        System.out.println("test event received..");
        System.out.println("handle event start--" + event);
        try {
            Thread.currentThread().sleep(2000);
        } catch (Exception e) {}
    }
}

在handleEvent方法中,我僅僅只是打出了event監聽到了一些標志以及休息2秒,其實可以從event中拿到一些之前在Event中注入的屬性,以及當前的主題等等。

訂閱Activator

在訂閱者中,我還是將相應監聽的事件放在了Activator中,這個也是相當簡單,只需將EventHandler進行注冊並指定監聽的topic即可,代碼如下:

package cn.com.example;

import cn.com.event.handler.MyEventHandler;
import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceReference;
import org.osgi.framework.ServiceRegistration;
import org.osgi.service.event.Event;
import org.osgi.service.event.EventAdmin;
import org.osgi.service.event.EventConstants;
import org.osgi.service.event.EventHandler;

import java.util.Dictionary;
import java.util.HashMap;
import java.util.Hashtable;

/**
 * Created by xiaxuan on 16/7/15.
 */
public class Activator4 implements BundleActivator {

    private ServiceReference sr;

    EventAdmin eventAdmin = null;

    HashMap properties = null;

    Event event = null;

    /**
     * event  topic
     */
    final static String[] topic = {"my_osgi_test_event"};

    ServiceRegistration registration = null;

    public void start(BundleContext context) throws Exception {
        System.out.println("activator4 start");
        Dictionary dict = new Hashtable();
        dict.put(EventConstants.EVENT_TOPIC, topic);
        EventHandler eventHandler = new MyEventHandler();
        //registering the eventHandler
        registration = context.registerService(EventHandler.class.getName(), eventHandler, dict);
        if (registration != null) {
            System.out.println("event handler registered.");
        }
    }

    public void stop(BundleContext context) throws Exception {
        registration.unregister();
        System.out.println("event handler unregistered!");
    }
}

使用EventHandler的方法和之前注冊其他服務的方式相同,都是通過context.registerService的方式,在指定訂閱的topic之後,就可以進行進行Bundle之間的通信了。

Bundle通信

在啟動karaf之前,需要改變我們的karaf插件,karaf插件需要再啟動一個feature來支持Eventadmin同性,在karaf插件中增加的如下:


 eventadmin
 

這個寫在configuration中,這樣在karaf啟動時候同樣回家再eventadmin這個feature,如果不加載這個feature,會報空指針異常,這種feature加載的方式並不夠優雅,還有其他方式的加載辦法,但一時沒有找到,日後找到了再提一下.
啟動karaf之後,觀察控制台,就能清楚的看到我們的事件的發布和訂閱了,如下:

這裡進行圖片描述vc7Sw8e1xMrCvP61xLeisry2qdTEtrzV/bOjvfjQ0KGjPC9wPg0KPGhyIC8+DQo8aDIgaWQ9"總結">總結

以上中,事件的發布和訂閱中,發布Event的Bundle和訂閱的Bundle之間可以沒有任何的關系它們之間以 Event Admin 服務為中間人 (Broker),以事件 (Event) 為消息載體,進行 Bundle 間的松散協作。

osgi中的Event Admin的事件發布相對與各種消息中間件的發布訂閱來說,功能上還是單薄了許多,而且在發布過程中,事件並不能持久化保存。意味著如果當前Bundle重啟,那麼Event就會全部丟失。

在事件的發布訂閱中,發布事件的Bundle發布事件之後,如果訂閱的Bundle處於未Active狀態的時候,這個時候發布的事件就不會被接收到,並且在隨後也不會被接收到。

據上,在使用Bundle之間的通信的時候,還是更加推薦使用各種開源的消息中間件來進行消息通信更好。

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved