首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> J2EE

OSGi 服務:極適合 SOA 架構的動態服務模型深度解析

     編輯:J2EE

本文為《你好,OSGi》系列第四部分,深入講述 OSGi 服務機制。OSGi 架構極適合實現面向服務應用 (SOA):Bundle 可導出服務,其他 Bundle 無需知曉來源 Bundle 任何資訊即可消費服務。OSGi 隱藏真實服務實作類的能力,為 SOA 提供優秀的類與介面組合。

核心概念

OSGi 框架中,來源 Bundle 在容器註冊 POJO 物件(無需實作介面或繼承超類),可在一或多個介面名下註冊對外提供服務。目標 Bundle 向容器請求特定介面下的服務,發現後綁定至介面並調用方法。

5.1 導出服務實作

更新 HelloService Bundle 導出 HelloServiceImpl 物件:

  1. 修改 MANIFEST.MF 導入 org.osgi.framework 套件
  2. 建立 HelloServiceActivator.java(代碼清單 7)
public class HelloServiceActivator implements BundleActivator {
    ServiceRegistration helloServiceRegistration;
    public void start(BundleContext context) throws Exception {
        HelloService helloService = new HelloServiceImpl();
        helloServiceRegistration = context.registerService(
            HelloService.class.getName(), helloService, null);
    }
    public void stop(BundleContext context) throws Exception {
        helloServiceRegistration.unregister();
    }
}

registerService() 三參數:介面名稱(或字串陣列多介面)、服務實體物件、服務屬性字典(供消費者過濾)。

  1. 修改 MANIFEST.MF 設定 Bundle-Activator: com.javaworld.sample.service.impl.HelloServiceActivator

容器啟動 Bundle 時將控制權交給 Activator,註冊服務至登記處。

5.2 導入服務消費

修改 HelloWorld Bundle 成為消費者,更新 Activator.java(代碼清單 8):

public class Activator implements BundleActivator {
    ServiceReference helloServiceReference;
    public void start(BundleContext context) throws Exception {
        System.out.println("HelloWorld!!");
        helloServiceReference = context.getServiceReference(HelloService.class.getName());
        HelloService helloService = (HelloService) context.getService(helloServiceReference);
        System.out.println(helloService.sayHello());
    }
    public void stop(BundleContext context) throws Exception {
        System.out.println("Goodbye World!!");
        context.ungetService(helloServiceReference);
    }
}

getServiceReference() 返回註冊於介面下的服務引用(多服務時返回最高排名者)。取得引用後調用 getService() 獲取真實服務物件。

5.3 建立服務工廠

預設單一服務物件共享。若需:
• 每消費者 Bundle 返回不同服務實例
• 服務物件昂貴(如資料庫連線)採延遲建立
解法:實作 ServiceFactory 介面註冊為服務(代碼清單 9)。

public class HelloServiceFactory implements ServiceFactory {
    private int usageCounter = 0;
    public Object getService(Bundle bundle, ServiceRegistration registration) {
        System.out.println("Create object of HelloService for " + bundle.getSymbolicName());
        usageCounter++;
        System.out.println("Number of bundles using service " + usageCounter);
        return new HelloServiceImpl();
    }
    public void ungetService(Bundle bundle, ServiceRegistration registration, Object service) {
        System.out.println("Release object of HelloService for " + bundle.getSymbolicName());
        usageCounter--;
        System.out.println("Number of bundles using service " + usageCounter);
    }
}

修改 HelloServiceActivator 註冊工廠而非實體(代碼清單 10)。執行時服務計數器隨 Bundle 啟動/停止增減。

5.4 追蹤服務動態變化

多 Bundle 註冊同介面服務時,容器返回最高排名服務。若消費者需知悉服務註冊/註銷時機,使用 ServiceTracker(代碼清單 11-12)。

public class HelloServiceTracker extends ServiceTracker {
    public HelloServiceTracker(BundleContext context) {
        super(context, HelloService.class.getName(), null);
    }
    public Object addingService(ServiceReference reference) {
        System.out.println("Inside HelloServiceTracker.addingService " + reference.getBundle());
        return super.addingService(reference);
    }
    public void removedService(ServiceReference reference, Object service) {
        System.out.println("Inside HelloServiceTracker.removedService " + reference.getBundle());
        super.removedService(reference, service);
    }
}

更新 Activator 使用 Tracker 管理服務(代碼清單 12)。啟動/停止 HelloService Bundle 時,容器將調用 Tracker 的 addingService()/removedService()。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved