1.案例代码
public class SPIDemo {
public static void main(String[] args) {
ServiceLoader<RunInterface> load = ServiceLoader.load(RunInterface.class);
Iterator<RunInterface> iterator = load.iterator();
while (iterator.hasNext()) {
RunInterface runInterface = iterator.next();
runInterface.run();
}
}
}
接口
public interface RunInterface {
void run();
}
实现类
public class Car implements RunInterface {
@Override
public void run() {
System.out.println("小汽车四个轮跑");
}
}
public class Human implements RunInterface {
@Override
public void run() {
System.out.println("人类两条腿跑");
}
}
resource目录下新建META-INF/META-INF/services文件夹
文件夹下新建文件,文件名为需要调用的接口名的全限定类名
2.源码跟进
2.1 实例化ServiceLoader与LazyIterator
ServiceLoader.load(Class service);
获取应用类加载器ApplicationClassLoad,用于加载用户自定义的类
创建一个ServiceLoader
同时创建一个LazyIterator对象
LazyIterator 为ServiceLoader的内部类
2.2 加载资源与实例化服务
获取迭代器
加载资源
当调用 iterator.hasNext() javaspi将完成资源的加载与实例化
此处的lookupIterator 即为 ServiceLoader 的内部类LazyIterator
java.util.ServiceLoader.LazyIterator#hasNext
java.util.ServiceLoader.LazyIterator#hasNextService
加载资源
拿到接口的名字与 META-INF/services/ 拼接,通过类加载器去加载资源
解析资源
一次解析一行,存入LIst集合name中
拿到了需要调用的服务的全限定类名
然后就是实例化
java.util.ServiceLoader.LazyIterator#next
java.util.ServiceLoader.LazyIterator#nextService
最终通过Class.forName实例化