簡單的 ServiceLoader 示例
ServiceLoader 是一種簡單易用的內建機制,用於動態載入介面實現。使用服務載入器 - 提供即時(但不是佈線)的方法 - 可以在 Java SE 中構建簡單的依賴注入機制。使用 ServiceLoader 介面和實現分離變得自然,程式可以方便地擴充套件。實際上,很多 Java API 都是基於 ServiceLoader 實現的
基本概念是
- 在服務介面上執行
- 通過
ServiceLoader
獲取服務的實現 - 提供服務的實現
讓我們從介面開始,把它放在一個 jar 中,例如 accounting-api.jar
package example;
public interface AccountingService {
long getBalance();
}
現在我們在名為 accounting-impl.jar
的 jar 中提供該服務的實現,其中包含服務的實現
package example.impl;
import example.AccountingService;
public interface DefaultAccountingService implements AccouningService {
public long getBalance() {
return balanceFromDB();
}
private long balanceFromDB(){
...
}
}
此外,accounting-impl.jar
包含一個檔案,宣告此 jar 提供了 AccountingService
的實現。該檔案必須具有以 META-INF/services/
開頭的路徑,並且必須與介面的完全限定名稱具有相同的名稱 :
META-INF/services/example.AccountingService
該檔案的內容是實現的完全限定名稱:
example.impl.DefaultAccountingService
鑑於兩個 jar 都在程式的類路徑中,消耗 AccountingService
,可以使用 ServiceLauncher 獲取服務的例項
ServiceLoader<AccountingService> loader = ServiceLoader.load(AccountingService.class)
AccountingService service = loader.next();
long balance = service.getBalance();
由於 ServiceLoader
是 Iterable
,它支援多個實現提供程式,程式可以從中選擇:
ServiceLoader<AccountingService> loader = ServiceLoader.load(AccountingService.class)
for(AccountingService service : loader) {
//...
}
請注意,在呼叫 next()
時,將始終建立一個新例項。如果要重用例項,則必須使用 ServiceLoader 的 iterator()
方法或 for-each 迴圈,如上所示。