[摘]基於 OSGi 的面向服務的組件編程

一. OSGi 簡史

OSGi 是由 1999 年成立的 OSGi 聯盟提出的一個開放的服務規範,最初的目的是爲嵌入式設備,確切地說是爲可以通過網絡訪問的設備提供一個通用的軟件運行平臺,屏蔽不同設備之間的硬件和操作系統差異,使軟件可以動態地部署和更新。後來 Eclipse 組織注意到了 OSGi 的優點,決定將 Eclipse3.0 及後續版本的插件體系結構基於 OSGi 來實現,並專門成立了一個子項目 Equinox 來實現 OSGi R4 規範,把 Equinox 作爲 Eclipse 的底層運行平臺。Eclipse 組織的這一決定帶來了雙贏的局面,今天的 Eclipse 由於其出色的可擴展的體系結構,已經不再是一個單純的 Java IDE,而是一個開放的開發平臺,一個通用的可擴展的軟件框架,OSGi 也不再侷限於嵌入式領域,而是成爲了一個通用的動態組件開發環境,在桌面,服務器端等領域得到了大量應用。

對模塊化的支持是 Java 的一個重要的發展方向,目前 Java 的模塊化標準還存在着JSR 277:Java Module Systems 和 JSR 291:Dynamic Component Support for Java 之爭論,其中JSR291 的主要目的就要將 OSGi 引入到 Java 標準中去,JSR277 則是 SUN 發起的一個Java 模塊化標準。但 OSGi 事實上已經得到了許多國際IT大企業的支持,並且已經有許多商業軟件產品基於 OSGi 來開發,如 IBM 包括 Websphere Application Server(WAS), Rational Software Architecture(RSA) 在內的許多重量級軟件產品均已基於 OSGi 來實現,著名的 IoC 框架 Spring 正在整合 OSGi 技術,現在基於 Eclipse 開發 RCP,插件程序也非常流行,可以預見基於OSGi 的 Java 應用程序將會越來越多,也將會有越來越多的軟件開發組織改變其軟件設計思想和開發方式,擁抱 OSGi 並開始享受 OSGi 帶來的好處。





回頁首


二. 使用 Eclipse 開發 OSGi 應用

本文假設讀者已經瞭解 OSGi 編程的基本概念以及如何在 Eclipse 環境中來開發OSGi Bundle。如果您還不瞭解這些知識,可以先閱讀相關資料如: http://www.eclipse.org/equinox網站以及 developerworks 網站上的文章: 利用 Eclipse 開發基於 OSGi 的 Bundle 應用

Eclipse 開發平臺中對基於 OSGi 開發應用程序已經提供了較爲完善的支持,在 Eclipse 集成開發環境中可以輕鬆地完成對一個或多個 bundle 的開發、調試、部署、測試等工作。本文將基於 Equinox OSGi 框架,使用 Eclipse 開發平臺來開發一個示例性的系統管理程序,主要目的是給讀者演示基於 OSGi 開發一個應用程序的過程並讓讀者體會基於OSGi 編程帶來的模塊化,動態性,擴展性等優點。爲了便於讀者理解,本文會儘可能的保持代碼簡單易懂,本文中的代碼在 WindowsXP,Eclipse3.2,Sun JDK1.5 環境下測試通過。





回頁首


三. 需求分析與模塊劃分

OSGi 帶來了規範化的模塊劃分,低耦合的模塊間關係,統一的模塊開發方式,可動態插拔的模塊管理環境。開發 OSGi 應用程序的第一步是在需求分析的基礎上進行精心的模塊劃分,模塊劃分的原則是儘量保持單個模塊的獨立性,使模塊與模塊之間的耦合降到最小,每一個模塊暴露給其它模塊的信息最少,儘量讓模塊之間使用 OSGi 框架提供的服務註冊機制來通信。一般可採用一個模塊一個 Bundle 的方式,併爲每一個 Bundle 在 Eclipse 環境中建立一個 Project 來進行開發,由於模塊與模塊之間的耦合很小,各個 Bundle 之間並不會象傳統的開發方式中的各模塊之間那樣存在糾纏不清的包和類的引用關係,因此大部分Bundle的開發工作可以並行進行而不會互相影響。

本文實現的系統管理程序,可以提供一系列的系統管理服務來管理計算機內的各類設備。爲簡便起見,我們首先只實現一項管理服務:Monitor,此項服務可以監視計算機內各類設備的運行狀態,我們可以將整個軟件劃分爲如下的一些Bundle:

 

  • Services Bundle:在OSGi中,服務是通過Java的接口來定義的,我們可以把定義服務的Java接口集中一個Services Bundle中,並由這個Bundle向其它Bundle提供接口。
  • 服務提供者Bundle:實現Services Bundle提供的接口並向OSGi框架註冊服務。在本例中,我們要實現對各類設備的監視,對於每一個需要監視的設備,均可以實現一個單獨的服務提供者Bundle來提供相應的監視功能。
  • 服務使用者Bundle:引用Services Bundle提供的接口向OSGi框架請求相應的服務,本例中主要實現一個服務使用者Bundle,它是一個控制檯程序,用於執行相應的系統管理服務,並在控制檯中向用戶顯示相應的系統管理信息。

 

整個程序是由OSGi框架以及運行於OSGi框架內的一批Bundles組成,Bundle之間的協作關係見下圖:


圖1 程序的總體架構圖
程序的總體架構圖




回頁首


四. 實現Bundle

1. 實現Services Bundle

新建一個Eclipse plugin-in project,將其命名爲com.systemmanagement.services,注意創建OSGi Bundle工程時,一定要選中“an OSGi framework”做爲工程的目標平臺,並選擇Equinox或standard,這兩個選項的區別是:Equinox對OSGi 規範第4版進行了一些擴展,如果開發出來的Bundle希望能夠在其它的OSGi實現框架如Oscar,Knopflerfish上順利運行,此處最好選擇standard。這個Bundle的實現很簡單,它無需實現BundleActivator類,只需定義一個接口即可:


代碼清單1: MonitorService.java
                
package com.systemmanagement.services.monitor;

public interface MonitorService {
	public String getMonitorMessage();
}

同時勿忘在此Bundle的MANIFEST.MF文件中將相應的package導出:


代碼清單2:MANIFEST.MF
                
Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: Services Plug-in
Bundle-SymbolicName: com.systemmanagement.services
Bundle-Version: 1.0.0
Bundle-Vendor: cyz
Bundle-Localization: plugin
Export-Package: com.systemmanagement.services.monitor
            

如果將來需要擴充新的系統管理服務,需在此Bundle中增加新的接口並將其所屬的package在MANIFEST.MF文件中導出。

2. 實現服務提供者Bundle

新建一個Eclipse plugin-in project,將其命名爲com.systemmanagement.cpumonitor,此Bundle負責監視CPU,提供相應的監視信息,它需要實現services bundle提供的MonitorService接口,同時它需要向OSGi框架註冊服務,因此首先需要在其MANIFEST.MF文件中導入相應的包:


代碼清單3:MANIFEST.MF
                
Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: Cpumonitor Plug-in
Bundle-SymbolicName: com.systemmanagement.cpumonitor
Bundle-Version: 1.0.0
Bundle-Activator: com.systemmanagement.cpumonitor.CpuMonitorActivator
Bundle-Vendor: cyz
Bundle-Localization: plugin
Import-Package: com.systemmanagement.services.monitor,
                 org.osgi.framework;version="1.3.0"
            

此Bundle的實現主要包括兩部分工作:一個實現MonitorService的類,用於提供CPU的監視信息(如代碼清單4所示)。一個BundleActivator類用於在Bundle啓動時向OSGi框架註冊服務,在Bundle停止時將服務註銷(如代碼清單5所示)。


代碼清單4:CpuMonitor.java
                
Package com.systemmanagement.cpumonitor.impl;
import com.systemmanagement.services.monitor.MonitorService;

public class CpuMonitor implements MonitorService {
	public String getMonitorMessage() {
        return "CPU--溫度:40度,電壓:1.4v";
	}
}

代碼清單4僅爲演示之用途,在真正開發應用時,可以在此處實現真實的CPU監視功能,例如你可以使用Java的JNI機制來調用一些操作系統底層的或第三方的API獲得相關的CPU信息,這些技術與本文的主題OSGi關係不大,在此略過。


代碼清單5:CpuMonitorActivator.java
                
Package com.systemmanagement.cpumonitor;

import java.util.Hashtable;
import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceRegistration;
import com.systemmanagement.cpumonitor.impl.CpuMonitor;
import com.systemmanagement.services.monitor.MonitorService;

public class CpuMonitorActivator implements BundleActivator {
    private BundleContext context=null;
    private ServiceRegistration serviceRegistration=null;
    
    public void start(BundleContext context) throws Exception {
        this.context=context;
        MonitorService monitor=new CpuMonitor();
        Properties properties = new Properties();
        properties.put("device", "cpu");
        serviceRegistration=this.context.registerService(
            MonitorService.class.getName(), monitor, properties);	
    }

    public void stop(BundleContext context) throws Exception {
        serviceRegistration.unregister();
        context=null;
    }
}

代碼清單5中最重要的功能就是向OSGi框架註冊了一個Monitor服務,註冊服務時使用了一個Properties容器,容器中的key-value對說明了當前這個Monitor服務針對的是CPU,利用這個Properties容器,服務使用者Bundle就能夠判斷一個Monitor服務所針對的具體設備是什麼。

針對其它需監視的設備如內存,網卡,電源,風扇等,我們可以分別實現一個Bundle來提供相應的監視服務,其實現過程與com.systemmanagement.cpumonitor這個Bundle是完全類似的,在此不再贅述。

3. 實現服務使用者Bundle

新建一個Eclipse plugin-in project,將其命名爲com.systemmanagement.console,此Bundle是一個控制檯程序,它通過調用其它服務提供者Bundle提供的系統管理服務,向用戶提供系統管理信息。同樣首先需要在其MANIFEST.MF文件中導入相應的包:


代碼清單6:MANIFEST.MF
                
Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: Console Plug-in
Bundle-SymbolicName: com.systemmanagement.console
Bundle-Version: 1.0.0
Bundle-Activator: com.systemmanagement.console.ConsoleActivator
Bundle-Vendor: cyz
Bundle-Localization: plugin
Import-Package: com.systemmanagement.services.monitor,
                 org.osgi.framework;version="1.3.0",
                 org.osgi.util.tracker;version="1.3.1"
            

代碼清單6中導入的包org.osgi.util.tracker是OSGi框架提供的監視Bundle提供的服務是否可用的機制,下文將會詳述。

此Bundle的實現主要包括三部分工作:一個ServiceTracker類,用於監視服務提供者Bundle註冊的各類系統管理服務是否可用,並根據服務是否可用,採取相應的動作(如代碼清單7所示)。一個控制檯線程類,用於執行各類系統管理服務並向用戶提供相應的信息(如代碼清單8所示)。一個BundleActivator類用於在Bundle啓動時啓動Service Tracker服務監視系統管理服務是否可用,啓動控制檯線程類開始執行各類系統管理服務並顯示信息,在Bundle停止時停止Service Tracker服務和控制檯線程類。(如代碼清單9所示)。


代碼清單7: MonitorServiceTracker.java
                
package com.systemmanagement.console;

import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceReference;
import org.osgi.util.tracker.ServiceTrackerCustomizer;
import com.systemmanagement.services.monitor.MonitorService;

public class MonitorServiceTracker implements ServiceTrackerCustomizer {
	private ConsoleThread thread;
	private BundleContext bc;
	
	public MonitorServiceTracker(BundleContext bc,ConsoleThread thread) {
		this.thread = thread;
		this.bc = bc;
	}
	public Object addingService(ServiceReference reference) {
		MonitorService service = (MonitorService)bc.getService(reference);
		thread.addService(service);
		return service;
	}
	public void modifiedService(ServiceReference reference, Object serviceObject) {
		MonitorService service = (MonitorService)bc.getService(reference);
		thread.addService(service);
	}
	public void removedService(ServiceReference reference, Object serviceObject) {
		MonitorService service = (MonitorService)bc.getService(reference);
		thread.removeService(service);
	}
}

注意,在本文中只實現了Monitor一項服務,將來如需擴充到支持多項系統管理服務,可以爲每一項或某一類服務各自實現一個ServiceTracker類來監視相應服務的可用性。


代碼清單8:ConsoleThread.java
                
package com.systemmanagement.console;

import java.util.HashSet;
import java.util.Iterator;
import com.systemmanagement.services.monitor.MonitorService;

public class ConsoleThread extends Thread {
	private HashSet<MonitorService> monitorServices=new HashSet<MonitorService>();
	private boolean running = true;
	public ConsoleThread(){};
	
	public void addService(MonitorService service){
		this.monitorServices.add(service);
	}
	public void removeService(MonitorService service){
		this.monitorServices.remove(service);
	}
	public void run() {
		while (running) {
		    for(Iterator<MonitorService> it=this.monitorServices.iterator();it.hasNext();){
				MonitorService service=it.next();
				System.out.println(service.getMonitorMessage());
			}
			try {
				Thread.sleep(5000);
			} catch (InterruptedException e) {
				System.out.println("ManagementThread ERROR: " + e);
			}
		}
	}
	public void stopThread() {
		this.running = false;
		try {
			this.join();
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}
}

代碼清單8是一個多線程程序,爲演示之簡便,在此例中它只是用一個HashSet持有當前可用的系統管理服務,並無限循環,依次執行各項系統管理服務。在實際情況中,完全可以與用戶交互,根據用戶的指令來執行相應的系統管理服務。


代碼清單9:ConsoleActivator.java
                
package com.systemmanagement.console;

import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;
import org.osgi.util.tracker.ServiceTracker;
import org.osgi.util.tracker.ServiceTrackerCustomizer;
import com.systemmanagement.services.monitor.MonitorService;

public class ConsoleActivator implements BundleActivator {
	
	private BundleContext context = null;
	private ServiceTracker tracker = null;
	private ConsoleThread thread=new ConsoleThread();
	
	public void start(BundleContext context) throws Exception {
		this.context = context;
		tracker = new ServiceTracker(context, MonitorService.class.getName(),
				new MonitorServiceTracker(context,thread));
		tracker.open();
		
		this.thread.start();
	}

	public void stop(BundleContext context) throws Exception {
		tracker.close();
		this.thread.stopThread();
	}
}





回頁首


五.運行和測試基於OSGi的應用程序

一個基於OSGi的應用程序是由OSGi框架本身以及若干個Bundle組成,爲了對其進行運行和測試,通常需要將各個Bundle Project一一打包成Bundle(jar文件),並部署到一個OSGi框架中,還是比較麻煩的。幸運的是,Eclipse已經對此提供了很好的支持,Eclipse本身是基於OSGi框架Equinox的,在Eclipse環境中可直接將各Bundle部署到Equinox框架中並運行之,對開發者來說十分便利,其具體步驟如下:

在Eclipse中選擇Run-->Run...菜單,在彈出的Run配置面板的左側選中“Equinox OSGi Framework”,然後再選擇其上方的“New”按鈕創建一個新的運行配置,將其命名爲“systemmanagement”,再選擇右側的Deselect All按鈕,然後只選擇我們想要運行的4個Bundles:包括我們前面開發的3個Bundle以及OSGi框架本身org.eclipse.osgi,其中還可以設置各個Bundle的Start Level, Start Level可用於控制各Bundle的啓動順序,Start Level低的Bundle會優先啓動,例如我們可以將服務提供者Bundle cpumonitor的Start Level設爲1,而將服務使用者Bundle console的Start Level設爲2,如下圖所示:


圖2 Bundle的運行配置
Bundle的運行配置

在Eclipse環境中的運行結果如下圖,在控制檯中會不斷的顯示一些系統管理信息,同時也可在控制檯中運行各種OSGi控制檯命令,如ss命令可用於顯示各Bundle的狀態,讀者可以通過help命令瞭解更多的OSGi控制檯命令。


圖3 在Eclipse中的運行結果
在Eclipse中的運行結果

我們也需要了解如何讓這些Bundle脫離Eclipse環境來運行,首先需要將各個Bundle Project打包成一個Bundle(即一個jar文件),其步驟如下:

在Eclipse主菜單中選File->Export,再在彈出窗口中選擇Deployable plug-ins and fragments,再選下一步,在彈出窗口中選擇我們上面開發的三個Bundle project,並指定Bundle的輸出目錄,點Finish即可,如下圖所示:


圖4 導出Bundle
導出Bundle

然後可以在e:/system_management/plugins目錄下找到三個jar文件,現在我們需要一個OSGi框架來運行它們。Equinox是目前最流行的OSGi框架,Equinox本身也被打包成一個Bundle,在Eclipse安裝目錄的plugins目錄下即可找到它,如org.eclipse.osgi_3.2.0.v20060601.jar,將這個文件拷到e:/system_management目錄下。在命令提示符下進入e:/system_management目錄下,運行如下命令啓動Equinox:

java –jar org.eclipse.osgi_3.2.0.v20060601.jar –console

啓動之後會出現一個OSGi控制檯,並且已經啓動一個system bundle,這個bundle就是OSGi框架本身。現在我們可以在OSGi控制檯中手工安裝我們開發的三個Bundle,如下圖所示:


圖5 安裝Bundle
安裝Bundle

隨後,可以依次啓動三個Bundle,這樣整個應用就運行起來了,如下圖所示:


圖6 運行Bundle
運行Bundle

請保留這個OSGi控制檯並讓應用繼續運行,接下來我們還會在這個控制檯中進行一些操作來體驗OSGi的動態性。





回頁首


六. 體驗OSGi的動態性

除了模塊化以及面向服務編程之外,OSGi的另一個重要特點是其動態性,Bundle以及Bundle提供的服務可以隨時消失或者重新加入,而其它使用服務的Bundle可以感知服務是否可用,並動態地改變自己的行爲。應用程序在運行過程中,可以隨時增加新的Bundle,停止或卸載已有的Bundle,如果有新的服務加入進來,這個服務也能立即被其它Bundle使用並由此動態地改變整個應用程序的行爲,在整個動態改變的過程中,OSGi框架本身是穩定的,無需重啓。以下我們將通過一些示例來體驗OSGi的動態性:

我們現在想給應用增加一個監視內存運行狀態的功能,新建一個Eclipse plugin-in project,將其命名爲com.systemmanagement.memorymonitor,這個Bundle的實現過程與com.systemmanagement.cpumonitor基本類似,最主要的不同是實現MonitorService服務的那個類,如以下代碼所示,其它代碼可參見本文所附的代碼清單。


代碼清單10:MemoryMonitor.java
                
package com.systemmanagement.memorymonitor.impl;
import com.systemmanagement.services.monitor.MonitorService;

public class MemoryMonitor implements MonitorService {
	public String getMonitorMessage() {
		return "內存--物理內存總數:1G,可用數:300M";
	}
}

同樣,將這個Bundle export成一個jar文件到e:/system_management/plugins目錄下,安裝以及啓動這個Bundle,這時我們發現輸出的系統管理信息馬上改變了,如下圖所示:


圖7 安裝以及啓動一個新的Bundle
安裝以及啓動一個新的Bundle

再假定我們需要增強com.systemmanagement.cpumonitor這個Bundle的功能,讓其提供更多的CPU信息,我們可以修改其中的CpuMonitor.java類,如下所示:


代碼清單11:CpuMonitor.java
                
package com.systemmanagement.cpumonitor.impl;
import com.systemmanagement.services.monitor.MonitorService;

public class CpuMonitor implements MonitorService {
	public String getMonitorMessage() {
		return "CPU--溫度:40度,電壓:1.4v,CPU佔用率:20%";
	}
}

再將這個Bundle export成一個jar文件,放到e:/system_management/plugins目錄下,並在OSGi控制檯中使用update命令更新這個Bundle,我們發現輸出的CPU監視信息馬上改變了,如下圖所示:


圖8 更新Bundle
更新Bundle

讀者還可以在OSGi控制檯中嘗試使用start,stop等命令啓動和停止一些Bundle,觀察輸出信息的改變,由此來體驗一下OSGi的動態性。

由於基於OSGi的應用程序具有高度的模塊化和動態性的特點,使得要對其進行擴展也變得非常的方便:一般來說,擴展就是增加新的Bundle,對其它Bundle基本無影響,如上面的例子所示,我們很方便地爲應用程序增加了新的功能,更新了它已有的功能,而整個應用程序甚至都不需要重啓。Equinox同時還借用了Eclipse中的擴展點的機制,利用擴展點,可以方便的爲已有的Bundle擴展功能,但擴展點這一套機制目前還不是OSGi規範中定義的特性,僅是Equinox這一實現平臺擴展出來的功能,使用了擴展點的Bundle將有可能不能在其它的OSGi實現框架中正常運行,這需要開發者權衡選擇。





回頁首


七.發佈應用程序

在上一節中我們在OSGi控制檯中運行我們的系統管理程序,其中還需要手工install, start各個Bundle,顯然這很麻煩,不太象一個真正的應用程序,本節將介紹如何構造出一個完整的基於OSGi的應用程序。

首先,Equinox提供了在啓動框架時自動安裝Bundle以及啓動Bundle的功能,這是通過定義config.ini文件來實現的,應用程序的目錄結構如下:

E:/SYSMGT_APP1
│  run.bat
│  org.eclipse.osgi_3.2.0.v20060601.jar
├─configuration
│      config.ini
└─plugins
       com.systemmanagement.console_1.0.0.jar
       com.systemmanagement.cpumonitor_1.0.0.jar
       com.systemmanagement.services_1.0.0.jar

config.ini文件的內容如下:

osgi.bundles=plugins/com.systemmanagement.cpumonitor_1.0.0.jar@1:start, 
 plugins/com.systemmanagement.console_1.0.0.jar@2:start, 
 plugins/com.systemmanagement.services_1.0.0.jar

其中的@1,@2用於指定Bundle的Start Level, start表示當OSGi框架啓動後即自動啓動此Bundle。而run.bat是一個批處理程序,其內容如下:

java –jar org.eclipse.osgi_3.2.0.v20060601.jar -console

現在只需運行run.bat即可運行我們的系統管理應用程序了。

Eclipse中還提供了兩個Bundle, org.eclipse.equinox.common和org.eclipse.update.configurator,可用於自動發現和安裝指定目錄下新增加的Bundle。我們同樣可以在Eclipse的plugins目錄中找到這兩個Bundle並將它們拷到E:/SYSMGT_APP1/plugins目錄下,並修改config.ini文件的內容如下所示:

osgi.bundles=plugins/org.eclipse.equinox.common_3.2.0.v20060603.jar@1:start,
 plugins/org.eclipse.update.configurator_3.2.0.v20060605.jar@2:start,
 plugins/com.systemmanagement.cpumonitor_1.0.0.jar@2:start, 
 plugins/com.systemmanagement.console_1.0.0.jar@3:start

這樣,當org.eclipse.update.configurator Bundle啓動時,它會去自動發現和安裝plugins目錄新增的Bundle,但需注意,它並不能自動啓動這些Bundle,OSGi協議目前也沒有提供這樣的標準服務來自動安裝,管理和啓動Bundle,我們可以使用如下的一些解決方案來更好地管理和分發Bundle:

  • 利用Eclipse的Update Manager:Eclipse Update Manager提供了一批API用於管理,下載,升級,安裝Feature,一個Feature是一批Bundle的集合, 是下載和安裝的最小單位。但Feature是Eclipse定義的,不是OSGi協議中定義的特性。
  • 使用FileInstall Bundle,這個Bundle可以監視某一個目錄,如果這個目錄中新增加了Bundle,它會自動將其install,如果有Bundle被更新了,它會自動將其update,如果有Bundle從此目錄被移走,它會自動將其uninstall。可到 http://www.aqute.biz/Code/FileInstall下載這個Bundle,它可以運行於任何OSGi框架中。
  • 在Equinox孵化器(incubator)中有一個org.eclipse.equinox.simpleconfigurator,可用於管理和控制已安裝的Bundle, 包括設置啓動級別並自動啓動它們。可訪問http://www.eclipse.org/equinox/incubator併到其CVS庫中下載




回頁首


八. 小結

本文介紹了基於OSGi開發一個應用程序的完整流程,包括模塊劃分,Bundle的設計與開發,部署與測試,發佈應用程序等,並演示了基於OSGi編程所具有的模塊化,面向服務,動態性,易擴展等優點。基於組件或構件編程是學術界提了多年的思想,筆者認爲OSGi是一個比較徹底地體現這種思想的編程模型,基於OSGi編程將帶來軟件設計以及開發方式的改變並由此帶來軟件生產效率的極大提升。

 
發佈了51 篇原創文章 · 獲贊 0 · 訪問量 33萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章