简单的 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 循环,如上所示。