ServiceLoader源码解析
示例代码
public class MyTest01 {
public static void main(String[] args) {
ServiceLoader<Driver> loader = ServiceLoader.load(Driver.class);
Iterator<Driver> iterator = loader.iterator();
while (iterator.hasNext()){
Driver dirver = iterator.next();
System.out.println(dirver.getClass());
}
}
}
首先我们看一下示例代码的步骤
1. 执行ServiceLoader.load()方法
ServiceLoader.load()
public static <S> ServiceLoader<S> load(Class<S> service) {
// 获取当前线程的上下文类加载器
ClassLoader cl = Thread.currentThread().getContextClassLoader();
return ServiceLoader.load(service, cl);
}
初始化ServiceLoader (private内部构造器)
private ServiceLoader(Class<S> svc, ClassLoader cl) {
service = Objects.requireNonNull(svc, "Service interface cannot be null");
// 如果线程上下文加载器为空, 则使用ClassLoader.getSystemClassLoader()即AppClassLoader
loader = (cl == null) ? ClassLoader.getSystemClassLoader() : cl;
acc = (System.getSecurityManager() != null) ? AccessController.getContext() : null;
// 重新加载
reload();
}
2. 获取迭代器
loader.iterator()
public Iterator<S> iterator() {
return new Iterator<S>() {
// 实际上是包装了 provider.entrySet() 的迭代器
// provider是对提供者列表的集合
Iterator<Map.Entry<String,S>> knownProviders
= providers.entrySet().iterator();
public boolean hasNext() {
if (knownProviders.hasNext())
return true;
return lookupIterator.hasNext();
}
public S next() {
if (knownProviders.hasNext())
return knownProviders.next().getValue();
// 迭代器的next()方法调用了lookupIterator的next()方法
return lookupIterator.next();
}
public void remove() {
throw new UnsupportedOperationException();
}
};
}
LazyIterator
上面获取迭代器的源码中提到了lookupIterator, lookupIterator是LazyIterator
的实例
// 实现Iterator迭代器接口
private class LazyIterator
implements Iterator<S>
{
...
private LazyIterator(Class<S> service, ClassLoader loader) {
// 设置要加载的类型
this.service = service;
// 设置类加载器, 也就是线程上下文加载器
this.loader = loader;
}
// LazyIterator迭代器的next()方法调用了nextService()方法
// nextService()方法实现了通过Class.forName()加载类, 当然这里面指定了类加载器
private S nextService() {
...
try {
c = Class.forName(cn, false, loader);
} catch (ClassNotFoundException x) {
fail(service,
"Provider " + cn + " not found");
}
...
}
...
}
看到这里, 相必大家已经清楚了ServiceLoader.load()方法的过程, 简单总结一下:
- 设置要加载的类和类加载器(使用的是线程上下文的类加载器)
- 通过迭代器可以遍历获取到的服务提供者(即已经加载的类的实例), 实际上是对
LazyIterator
的包装 - 最终,
LazyIterator
是通过Class.forName
来通过指定的类加载器加载类
那么, 最后还有一个问题, LazyIterator
是在哪里初始化的?
reload()
public void reload() {
// 清空provider, providers按照实例化顺序缓存服务提供者
providers.clear();
// 实例化LazyIterator, LazyIterator是一个静态内部类用来实现 fully-lazy provider lookup
lookupIterator = new LazyIterator(service, loader);
}