ServiceLoader是SPI的是一种实现,所谓SPI,即Service Provider Interface,用于一些服务提供给第三方实现或者扩展,可以增强框架的扩展或者替换一些组件。
要配置在相关项目的固定目录下:
resources/META-INF/services/接口全称。
这个在大数据的应用中颇为广泛,比如Spark2.3.1 的集群管理器插入:
private def getClusterManager(url: String): Option[ExternalClusterManager] = {
val loader = Utils.getContextOrSparkClassLoader
val serviceLoaders =
ServiceLoader.load(classOf[ExternalClusterManager], loader).asScala.filter(_.canCreate(url))
if (serviceLoaders.size > 1) {
throw new SparkException(
s"Multiple external cluster managers registered for the url $url: $serviceLoaders")
}
serviceLoaders.headOption
}
配置是在
spark sql数据源的接入,新增数据源插入的时候可以采用这种方式,要实现的接口是DataSourceRegister。
简单测试
首先实现一个接口
package bigdata.spark.services;
public interface DoSomething {
public String shortName(); //可以制定实现类名加载
public void doSomeThing();
}
然后将接口配置在resources/META-INF/services/
实现该接口
package bigdata.spark.services;
public class SayHello implements DoSomething {
@Override
public String shortName() {
return "SayHello";
}
@Override
public void doSomeThing() {
System.out.println("hello !!!");
}
}
测试
package bigdata.spark.services;
import java.util.ServiceLoader;
public class test {
static ServiceLoader<DoSomething> loader = ServiceLoader.load(DoSomething.class);
public static void main(String[] args){
for(DoSomething sayhello : loader){
//要加载的类名称我们可以制定
if(sayhello.shortName().equalsIgnoreCase("SayHello")){
sayhello.doSomeThing();
}
}
}
}
输出结果如下:
这个主要是为讲自定义数据源作准备。
欢迎订阅浪尖知识星球,跟450人一起学习。