//ServiceLoader实现了Iterable接口,可以遍历所有的服务实现者
public final class ServiceLoader
implements Iterable{//查找配置文件的目录
private static final String PREFIX = "META-INF/services/";//表示要被加载的服务的类或接口
private final Classservice;//这个ClassLoader用来定位,加载,实例化服务提供者
private finalClassLoader loader;//访问控制上下文
private finalAccessControlContext acc;//缓存已经被实例化的服务提供者,按照实例化的顺序存储
private LinkedHashMap providers = new LinkedHashMap<>();//The current lazy-lookup iterator
privateLazyIterator lookupIterator;//重新加载,就相当于重新创建ServiceLoader了,用于新的服务提供者安装到正在运行的Java虚拟机中的情况
public voidreload() {//清空缓存中所有已实例化的服务提供者
providers.clear();//新建一个迭代器,该迭代器会从头查找和实例化服务提供者
lookupIterator = newLazyIterator(service, loader);
}//私有构造器//使用指定的类加载器和服务创建服务加载器//如果没有指定类加载器,使用系统类加载器,就是应用类加载器。
private ServiceLoader(Classsvc, ClassLoader cl) {
service= Objects.requireNonNull(svc, "Service interface cannot be null");
loader= (cl == null) ?ClassLoader.getSystemClassLoader() : cl;
acc= (System.getSecurityManager() != null) ? AccessController.getContext() : null;
reload();
}//解析失败处理的方法
private static void fail(Class>service, String msg, Throwable cause)throwsServiceConfigurationError
{throw new ServiceConfigurationError(service.getName() + ": " +msg,
cause);
}private static void fail(Class>service, String msg)throwsServiceConfigurationError
{throw new ServiceConfigurationError(service.getName() + ": " +msg);
}private static void fail(Class> service, URL u, intline, String msg)throwsServiceConfigurationError
{
fail(service, u+ ":" + line + ": " +msg);
}//解析服务提供者配置文件中的一行//首先去掉注释校验,然后保存//返回下一行行号//重复的配置项和已经被实例化的配置项不会被保存
private int parseLine(Class> service, URL u, BufferedReader r, intlc,
Listnames)throwsIOException, ServiceConfigurationError
{//读取一行
String ln =r.readLine();if (ln == null) {return -1;
}//#号代表注释行
int ci = ln.indexOf('#');if (ci >= 0) ln = ln.substring(0, ci);
ln=ln.trim();int n =ln.length();if (n != 0) {if ((ln.indexOf(' ') >= 0) || (ln.indexOf('\t') >= 0))
fail(service, u, lc,"Illegal configuration-file syntax");int cp = ln.codePointAt(0);if (!Character.isJavaIdentifierStart(cp))
fail(service, u, lc,"Illegal provider-class name: " +ln);for (int i = Character.charCount(cp); i < n; i +=Character.charCount(cp)) {
cp=ln.codePointAt(i);if (!Character.isJavaIdentifierPart(cp) && (cp != '.'))
fail(service, u, lc,"Illegal provider-class name: " +ln);
}if (!providers.containsKey(ln) && !names.contains(ln))
names.add(ln);
}return lc + 1;
}//解析配置文件,解析指定的url配置文件//使用parseLine方法进行解析,未被实例化的服务提供者会被保存到缓存中去
private Iterator parse(Class>service, URL u)throwsServiceConfigurationError
{
InputStream in= null;
BufferedReader r= null;
ArrayList names = new ArrayList<>();try{
in=u.openStream();
r= new BufferedReader(new InputStreamReader(in, "utf-8"));int lc = 1;while ((lc = parseLine(service, u, r, lc, names)) >= 0);
}catch(IOException x) {
fail(service,"Error reading configuration file", x);
}finally{try{if (r != null) r.close();if (in != null) in.close();
}catch(IOException y) {
fail(service,"Error closing configuration file", y);
}
}returnnames.iterator();
}//Private inner class implementing fully-lazy provider lookup//服务提供者查找的迭代器
private classLazyIteratorimplements Iterator{//服务提供者接口
Classservice;//类加载器
ClassLoader loader;//保存实现类的url
Enumeration configs = null;//保存实现类的全名
Iterator pending = null;//迭代器中下一个实现类的全名
String nextName = null;private LazyIterator(Classservice, ClassLoader loader) {this.service =service;this.loader =loader;
}private booleanhasNextService() {if (nextName != null) {return true;
}if (configs == null) {try{
String fullName= PREFIX +service.getName();if (loader == null)
configs=ClassLoader.getSystemResources(fullName);elseconfigs=loader.getResources(fullName);
}catch(IOException x) {
fail(service,"Error locating configuration files", x);
}
}while ((pending == null) || !pending.hasNext()) {if (!configs.hasMoreElements()) {return false;
}
pending=parse(service, configs.nextElement());
}
nextName=pending.next();return true;
}privateS nextService() {if (!hasNextService())throw newNoSuchElementException();
String cn=nextName;
nextName= null;
Class> c = null;try{
c= Class.forName(cn, false, loader);
}catch(ClassNotFoundException x) {
fail(service,"Provider " + cn + " not found");
}if (!service.isAssignableFrom(c)) {
fail(service,"Provider " + cn + " not a subtype");
}try{
S p=service.cast(c.newInstance());
providers.put(cn, p);returnp;
}catch(Throwable x) {
fail(service,"Provider " + cn + " could not be instantiated",
x);
}throw new Error(); //This cannot happen
}public booleanhasNext() {if (acc == null) {returnhasNextService();
}else{
PrivilegedAction action = new PrivilegedAction() {public Boolean run() { returnhasNextService(); }
};returnAccessController.doPrivileged(action, acc);
}
}publicS next() {if (acc == null) {returnnextService();
}else{
PrivilegedAction action = new PrivilegedAction() {public S run() { returnnextService(); }
};returnAccessController.doPrivileged(action, acc);
}
}public voidremove() {throw newUnsupportedOperationException();
}
}//获取迭代器//返回遍历服务提供者的迭代器//以懒加载的方式加载可用的服务提供者//懒加载的实现是:解析配置文件和实例化服务提供者的工作由迭代器本身完成
public Iteratoriterator() {return new Iterator() {//按照实例化顺序返回已经缓存的服务提供者实例
Iterator>knownProviders=providers.entrySet().iterator();public booleanhasNext() {if(knownProviders.hasNext())return true;returnlookupIterator.hasNext();
}publicS next() {if(knownProviders.hasNext())returnknownProviders.next().getValue();returnlookupIterator.next();
}public voidremove() {throw newUnsupportedOperationException();
}
};
}//为指定的服务使用指定的类加载器来创建一个ServiceLoader
public static ServiceLoader load(Classservice,
ClassLoader loader)
{return new ServiceLoader<>(service, loader);
}//使用线程上下文的类加载器来创建ServiceLoader
public static ServiceLoader load(Classservice) {
ClassLoader cl=Thread.currentThread().getContextClassLoader();returnServiceLoader.load(service, cl);
}//使用扩展类加载器为指定的服务创建ServiceLoader//只能找到并加载已经安装到当前Java虚拟机中的服务提供者,应用程序类路径中的服务提供者将被忽略
public static ServiceLoader loadInstalled(Classservice) {
ClassLoader cl=ClassLoader.getSystemClassLoader();
ClassLoader prev= null;while (cl != null) {
prev=cl;
cl=cl.getParent();
}returnServiceLoader.load(service, prev);
}/*** Returns a string describing this service.
*
*@returnA descriptive string*/
publicString toString() {return "java.util.ServiceLoader[" + service.getName() + "]";
}
}