//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() + "]";
}
}