2008-10-30 58 views

回答

18

Java 1.5中沒有內置任何內容。我自己實現了它;它不是太複雜。但是,當我們升級到Java 6時,我將不得不使用調用ServiceLoader來替換對我的實現的調用。我本可以在應用程序和加載器之間定義一個小橋樑,但我只在幾個地方使用它,而封裝器本身就是ServiceLoader的一個很好的候選者。

這是核心思想是:

public <S> Iterable<S> load(Class<S> ifc) throws Exception { 
    ClassLoader ldr = Thread.currentThread().getContextClassLoader(); 
    Enumeration<URL> e = ldr.getResources("META-INF/services/" + ifc.getName()); 
    Collection<S> services = new ArrayList<S>(); 
    while (e.hasMoreElements()) { 
    URL url = e.nextElement(); 
    InputStream is = url.openStream(); 
    try { 
     BufferedReader r = new BufferedReader(new InputStreamReader(is, "UTF-8")); 
     while (true) { 
     String line = r.readLine(); 
     if (line == null) 
      break; 
     int comment = line.indexOf('#'); 
     if (comment >= 0) 
      line = line.substring(0, comment); 
     String name = line.trim(); 
     if (name.length() == 0) 
      continue; 
     Class<?> clz = Class.forName(name, true, ldr); 
     Class<? extends S> impl = clz.asSubclass(ifc); 
     Constructor<? extends S> ctor = impl.getConstructor(); 
     S svc = ctor.newInstance(); 
     services.add(svc); 
     } 
    } 
    finally { 
     is.close(); 
    } 
    } 
    return services; 
} 

更好的異常處理是作爲練習留給讀者。另外,該方法可以被參數化爲接受調用者選擇的ClassLoader。

0

沒有可靠的方法來知道類路徑中的類是什麼。根據其documentation,ServiceLoader依靠外部文件來告訴它要加載哪些類;你可能想要做同樣的事情。基本的想法是用一個文件加載類的名字,然後用反射來實例化它/它們。

1

ServiceLoader是相當基本的,自1.3版以來一直在JDK中使用(非正式)。 ServiceLoader終於使它成爲一流的公民。它只是尋找一個爲你的接口命名的資源文件,它基本上捆綁在庫jar的META-INF目錄中。

該文件包含要加載的類的名稱。

所以,你有一個名爲文件:

META-INF /服務/ com.example.your.interface

和裏面是一個單行:com.you.your.interfaceImpl 。

代替ServiceLoader,我喜歡Netbeans Lookup。它適用於1.5(也許1.4)。

開箱即用,它與ServiceLoader完全相同,使用起來也很簡單。但它提供了更多的靈活性。

這裏有一個鏈接:http://openide.netbeans.org/lookup/

這裏有一個大約的ServiceLoader的文章,但它提到的Netbeans查找在底部: http://weblogs.java.net/blog/timboudreau/archive/2008/08/simple_dependen.html

-1

你有沒有想過使用OSGi框架的?

1

不幸的是,

沒有什麼內置的Java 1.5此...

是唯一的真理的一部分。

周圍有非標準sun.misc.Service

http://www.docjar.com/docs/api/sun/misc/Service.html

當心,這不是標準的J2SE API的一部分! 這是Sun JDK的非標準部分。 所以,如果你使用JRockit,那麼你不能依賴它。

1

這是一個老問題,但另一種選擇是使用包級別註釋。 查看我的聯繫方式:Find Java classes implementing an interface

軟件包級別註釋是package-info.java類中的註釋。

JAXB使用此代替服務加載器。我也認爲它比服務加載器更靈活。