Java 鬆綁 (三):利用 ServiceLoader 實作動態載入
在前兩篇文章中,我們看到了如何利用 Java 多型的技巧,鬆綁類別之間的關係;也看到如何透過動態載入的技巧,來鬆綁 Package。不過還不是很完美,至少我是這樣認為。
在「Java 鬆綁 (二):利用 Package 與動態載入徹底鬆綁」這篇文章中,係利用 Class.forName()
這個古老的方法來實作動態載入的功能,個人覺得非常的麻煩且缺乏彈性。比較理想的作法,係利用 Java EE 或者 SpingFramework 提供的 CDI (Contexts & Dependency Injection) 來實作這樣的要求。
不過 Java EE 容器雖然是 Java 世界中的標準,但重量級的執行環境,對於一個小的專案來說,非常的不值得;而 SpingFramework 雖然夠輕量化 (但近期的發展也趨向於重量),但卻不是標準的作法,實作與部署時必須考慮執行的環境中是否提供所需的條件。
所幸,Java 6 中提供了一個 java.util.ServiceLoader
類別,可以輔助我們簡化鬆綁的動作。
JAR 檔案的要求
要透過 java.util.ServiceLoader
來鬆綁 Package 時,你必須先在製作 Jar 檔前,在 META-INF/services/
目錄中,儲存一個文字檔,其檔案名稱必須為介面的 FQCN,而內容則為該 Jar 檔案中實作該介面的類別之 FQCN。
例如,以前文的例子,我在 impls-*.jar
檔案中,建立下列的目錄結構:
+ <ROOT> + META-INF/ + services/ - org.cdchen.serviceloaders.GreetingService
並在 META-INF/services/org.cdchen.serviceloaders.GreetingService
檔案中,定義下列的內容:
# 一行一個實作的類別之 FQCN. org.cdchen.serviceloaders.impls.HiGreetingService org.cdchen.serviceloaders.impls.HasEatingService
改寫呼叫端
接著,我們換用 java.util.ServiceLoader
來實作動態組入的功能吧:
package org.cdchen.serviceloaders.apps; import java.util.ServiceLoader; import org.cdchen.serviceloaders.GreetingService; public class ServiceLoaderMain { public static void main(String[] args) { // 載入 ServiceLoader. ServiceLoader<GreetingService> serviceLoader = ServiceLoader.load(GreetingService.class); // 遊走所有 service 物件. for (GreetingService service : serviceLoader) { GreetingServiceUtil.callService(service); } } }
沒錯,就這麼簡單!! 與前文的 TraditionalDynamicLoadingMain
相比,是否更簡潔一些??
執行
準備就緒後,如果要執行這個案例,我們只需要在啟動 JVM 時,指定 -cp
參數即可:
$ java -cp apis-0.0.1-SNAPSHOT.jar:impls-0.0.1-SNAPSHOP.jar \ org.cdchen.serviceloaders.apps.ServiceLoaderMain
就是這麼簡單,這麼愉快!!
這篇內容的 Trackback 網址:
附加檔案 | 大小 |
---|---|
serviceloader-labs-0.0.1-SNAPSHOT.tar_.gz | 4.22 KB |
- cdchen 的 BLOG
- 如果想要發表回應,請先登入 或 註冊。