許多開發者抱怨 OSGi 過於複雜、低階。但若從「為 Java 設計一個模組系統」的需求出發,逐步推導,你會發現 OSGi 的每一層設計都是為了解決具體痛點而自然演進的結果──這就是愛因斯坦剃刀:「事物應盡可能簡單,但不能更簡單」。
傳統 ClassPath 是扁平巨大清單,同名類別先載入者勝,導致 LinkageError、IncompatibleClassChangeError 或靜默錯誤。
解法: 每個模組一個專屬 ClassLoader,只載入自己能識別的類別,建立命名空間隔離。
完全隔離無法協作。需恢復可見性,但必須顯式、精確。
Java 缺乏「模組級」存取修飾符(public 太寬、package-private 太窄且編譯期無法強制)。
OSGi 方案:
類比購物:只買需要的商品(導入套件),而非「買下整間店(整包依賴)」。後者會導致「扇出效應」:依賴傳遞爆炸,下載海量無用 JAR(Maven 傳遞性依賴即此痛點)。
代價:無法完美處理「分裂套件」(同一套件分散在多模組),但可接受。
框架掃描導入/導出,建立Wiring(連線):導入套件連線到對應導出套件的載入器。
所有導入解析成功 → Bundle 進入 RESOLVED 狀態,可用。
副產品: 支援運行時安裝/更新/解除安裝 Bundle,框架自動重新解析受影響模組。動態性非強制,但提供選項。
1.0.0)。[1.0.0, 2.0.0) 含 1.0.0 至 2.0.0 不含)。建議語義化版本:主版本.次版本.修訂版本,主版本不相容、次版本相容新增、修訂版本修補。
JAR 已是標準部署單元。中繼資料放哪?
XML(早期):解析慢、需解壓、難手寫。
Java 註解(現代):需編譯成 class、載入器才能讀、掃描工具需解析位元組碼。
OSGi 選擇: META-INF/MANIFEST.MF ── JAR 標準位置、無需解壓即可讀首段、行長限制 72 字元(工具生成即可)。
現代工具(Bnd, Maven Bundle Plugin, Bundlor)自動從註解/DSL 生成 MANIFEST,兼得便利與效能。
介面解耦提供者/消費者,但誰實例化實作?
中心化 DI(Spring XML/God Class): 單一配置知曉所有模組,脆弱、難維護、違背模組化初衷。
OSGi 服務登記表:
OSGi 的複雜性源於它解決了真實世界的模組化難題:隔離、版本、動態、服務發現。
不足之處:版本語義對第三方庫無強制力、傳統庫假設扁平 ClassPath(Class.forName、字串類名)導致相容性挑戰。
但核心架構證明:模組化非輕量級可達成,OSGi 是最務實的演進結果。