JavaTM 2 Platform
Standard Ed. 6

java.util
類別 ServiceLoader<S>

java.lang.Object
  繼承者 java.util.ServiceLoader<S>
型別參數:
S - 要被此載入器載入的服務型別。
所有已實作的介面:
Iterable<S>

public final class ServiceLoader<S>
extends Object
implements Iterable<S>

一個簡單的服務提供者載入設施。

服務 是一個熟知的介面和類別(通常為抽象類別)集合。服務提供者 是服務的特定實作。提供者中的類別通常實作介面,並子類別化在服務本身中定義的子類別。服務提供者可以以擴展的形式安裝在 Java 平臺的實作中,也就是將 jar 檔案放入任意常用的擴展目錄中。也可通過將提供者加入應用程序類別路徑,或者通過其他某些特定於平臺的方式使其可用。

為了載入,服務由單個型別表示,也就是單個介面或抽象類別。(可以使用具體類別,但建議不要這樣做。)一個給定服務的提供者包含一個或多個具體類別,這些類別擴展了此服務型別,具有特定於提供者的資料和程式碼。提供者類別 通常不是整個提供者本身而是一個代理,它包含足夠的資訊來決定提供者是否能滿足特定請求,還包含可以根據需要創建實際提供者的程式碼。提供者類別的詳細資訊高度特定於服務;任何單個類別或介面都不能統一它們,因此這裡沒有定義任何這種型別。此設施唯一強制要求的是,提供者類別必須具有不帶參數的建構子,以便它們可以在載入中被實例化。

通過在資源目錄 META-INF/services 中放置提供者配置檔案 來標識服務提供者。檔案名稱是服務型別的完全限定二進制名稱。該檔案包含一個具體提供者類別的完全限定二進制名稱列表,每行一個。忽略各名稱周圍的空格、製表符和空行。註釋字元為 '#' ('\u0023', NUMBER SIGN);忽略每行第一個註釋字元後面的所有字元。檔案必須使用 UTF-8 編碼。

如果在多個配置檔案中指定了一個特定的具體提供者類別,或在同一配置檔案中多次被指定,則忽略重複的指定。指定特定提供者的配置檔案不必像提供者本身一樣位於同一個 jar 檔案或其他的分佈式單元中。提供者必須可以從最初為了定位配置檔案而查詢的類別載入器存取;注意,這不一定是實際載入檔案的類別載入器。

以延遲方式尋找和實例化提供者,也就是說根據需要進行。服務載入器維護到目前為止已經載入的提供者快取記憶體。每次調用 iterator 方法返回一個迭代器,它首先按照實例化順序產生快取記憶體的所有元素,然後以延遲方式尋找和實例化所有剩餘的提供者,依次將每個提供者添加到快取記憶體。可以通過 reload 方法清除快取記憶體。

服務載入器始終在調用者的安全上下文中執行。受信任的系統程式碼通常應當從特權安全上下文內部調用此類別中的方法,以及它們返回的迭代器的方法。

此類別的實例用於多個共時執行緒是不安全的。

除非另有指定,否則將 null 參數傳遞給此類別中的任何方法都會導致拋出 NullPointerException

範例假定服務型別為 com.example.CodecSet,它用來表示某些協議的編碼器/解碼器對集合。在這種情況下,它是一個具有兩種抽象方法的抽象類別:

public abstract Encoder getEncoder(String encodingName);
public abstract Decoder getDecoder(String encodingName);
每種方法都返回一個相應的物件;如果提供者不支持給定編碼,則返回 null。典型的提供者支持一種以上的編碼。

如果 com.example.impl.StandardCodecsCodecSet 服務的實作,則其 jar 檔案還包含一個指定如下的檔案:

META-INF/services/com.example.CodecSet

此檔案包含一行:

com.example.impl.StandardCodecs    # Standard codecs

CodecSet 類別在初始化時創建並保存一個服務實例:

private static ServiceLoader<CodecSet> codecSetLoader
= ServiceLoader.load(CodecSet.class);

為了尋找給定編碼名稱的編碼器,它定義了一個靜態處理器方法,該方法迭代所有已知並可用的提供者,只在找到適當的編碼器或迭代完提供者時返回。

public static Encoder getEncoder(String encodingName) {
for (CodecSet cp :codecSetLoader) {
Encoder enc = cp.getEncoder(encodingName);
if (enc != null)
return enc;
     }
return null;
 }

getDecoder 方法的定義類似。

使用注意事項 如果用於提供者載入的類別載入器的類別路徑包含遠端網路 URL,則這些 URL 將在搜尋提供者配置檔案的過程中被取消參考。

此活動是正常的,儘管它可能導致在 Web 伺服器日誌中創建一些令人迷惑的條目。但是,如果 Web 伺服器配置不正確,那麼此活動可能導致提供者載入演算法意外失敗。

如果請求的資源不存在,則 Web 伺服器應返回 HTTP 404 (Not Found) 回應。但有時會錯誤地將 Web 伺服器配置為返回 HTTP 200 (OK) 回應,並伴有這種情況下的 HTML 錯誤說明頁面。這會導致在此類別嘗試將 HTML 頁面作為提供者配置檔案進行解析時拋出 ServiceConfigurationError。此問題的最佳解決方案是修復配置錯誤的 Web 伺服器,以返回正確的回應程式碼 (HTTP 404) 以及 HTML 錯誤頁面。

從以下版本開始:
1.6

方法摘要
 Iterator<S> iterator()
          以延遲方式載入此載入器服務的可用提供者。
static
<S> ServiceLoader<S>
load(Class<S> service)
          針對給定服務型別創建新的服務載入器,使用當前執行緒的上下文類別載入器
static
<S> ServiceLoader<S>
load(Class<S> service, ClassLoader loader)
          針對給定服務型別和類別載入器創建新的服務載入器。
static
<S> ServiceLoader<S>
loadInstalled(Class<S> service)
          針對給定服務型別創建新的服務載入器,使用擴展類別載入器。
 void reload()
          清除此載入器的服務者快取記憶體,以重載所有服務者。
 String toString()
          返回一個描述此服務的字元串。
 
從類別 java.lang.Object 繼承的方法
clone, equals, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait
 

方法詳細資訊

reload

public void reload()
清除此載入器的服務者快取記憶體,以重載所有服務者。

調用此方法後,後續 iterator 方法的調用將以延遲方式從頭開始查詢和實例化提供者,正如新創建的載入器所做的一樣。

此方法用於新提供者可以被裝入運行的 Java 虛擬機器的情況。


iterator

public Iterator<S> iterator()
以延遲方式載入此載入器服務的可用提供者。

此方法返回的迭代器首先按實例化順序產生提供者快取記憶體的所有元素。然後以延遲方式載入和實例化所有剩餘的提供者,依次將每個提供者添加到快取記憶體。

要實作延遲,解析可用提供者配置檔案和實例化提供者的實際工作必須由迭代器本身完成。因此,如果提供者配置檔案違背指定的格式、指定了無法找到和實例化的提供者類別、實例化類別的結果不能分派服務型別、因為尋找和實例化下一個提供者而拋出任何其他異常或錯誤,那麼迭代器的 hasNextnext 方法將拋出 ServiceConfigurationError。要編寫健壯的程式碼,只需要在使用服務迭代器時捕獲 ServiceConfigurationError

如果拋出此類別錯誤,那麼迭代器的後續調用將盡力尋找和實例化下一個可用提供者,但通常無法保證此類別恢復操作。

設計注意事項 在那些情況下拋出錯誤顯得有些極端。此行為的基本原理是,錯誤的提供者配置檔案(如錯誤的類別檔案)表示 Java 虛擬機器配置和使用的方式存在嚴重的問題。因此,最好拋出一個錯誤而不是試圖恢復它,或者直接失敗(這樣更糟)。

此方法返回的迭代器不支持移除操作。調用其 remove 方法將導致拋出 UnsupportedOperationException

指定者:
介面 Iterable<S> 中的 iterator
返回:
以延遲方式載入此載入器服務提供者的迭代器

load

public static <S> ServiceLoader<S> load(Class<S> service,
                                        ClassLoader loader)
針對給定服務型別和類別載入器創建新的服務載入器。

參數:
service - 表示服務的介面或抽象類別
loader - 用來載入提供者配置檔案和提供者類別的類別載入器;如果要使用系統類別載入器(如果沒有,則使用引導類別載入器),則為 null
返回:
新的服務載入器

load

public static <S> ServiceLoader<S> load(Class<S> service)
針對給定服務型別創建新的服務載入器,使用當前執行緒的上下文類別載入器

調用以下形式的此便捷方法

ServiceLoader.load(service)
等價於:
ServiceLoader.load(service,
Thread.currentThread().getContextClassLoader())

參數:
service - 表示服務的介面或抽象類別
返回:
新的服務載入器

loadInstalled

public static <S> ServiceLoader<S> loadInstalled(Class<S> service)
針對給定服務型別創建新的服務載入器,使用擴展類別載入器。

此便捷方法查詢擴展類別載入器,稱其為 extClassLoader,然後返回

ServiceLoader.load(service, extClassLoader)

如果無法找到擴展類別載入器,則使用系統類別載入器;如果沒有系統類別載入器,則使用引導類別載入器。

此方法僅供安裝所需的提供者時使用。所得服務只尋找和載入已經裝入當前 Java 虛擬機器的提供者;忽略應用程序類別路徑上的提供者。

參數:
service - 表示服務的介面或抽象方法
返回:
新的服務載入器

toString

public String toString()
返回一個描述此服務的字元串。

覆寫:
類別 Object 中的 toString
返回:
一個描述字元串

JavaTM 2 Platform
Standard Ed. 6

提交錯誤或意見

版權所有 2008 Sun Microsystems, Inc. 保留所有權利。請遵守GNU General Public License, version 2 only