SPI ServiceLoader源码分析
public class ddd { public static void main(String[] args) { ServiceLoader1<Hello> sl = ServiceLoader1.load(Hello.class);//传进去了Hello.class和线程上下文类加载器。 for(Hello h : sl) {//调用sl的iterator() h.say();//com.ssss.impl.CHello@1324409e, } } }
package com.ssss; /* 服务提供者加载机制。针对SPI设计出来的。 服务是接口或抽象类。服务提供者是服务接口的实现。ServiceLoader是加载实现类的。服务提供者是jdbc数据库驱动。 不是线程安全的。 文件名是接口,文件内容是实现。 @since 1.6 1.6才开始加入, 根据META-INF/services/文件去加载相应的实现类。 */ public final class ServiceLoader1<S> implements Iterable<S>{ private static final String PREFIX = "META-INF/services/";//指明了路径是在META-INF/services/下。 // 传进来的接口的class。正在加载的服务的类或接口。 private final Class<S> service; // 线程上下文加载器。类加载器。 private final ClassLoader loader; // 权限控制上下文。创建ServiceLoader时获取的访问控制上下文。 private final AccessControlContext acc; // 服务提供者的缓存,服务是接口,服务提供者是接口的实现。 private LinkedHashMap<String,S> providers = new LinkedHashMap<>(); // for循环遍历时候调用的是这个在遍历。用于类的懒加载,只有在迭代时加载。 private LazyIterator lookupIterator; public void reload() {//构造函数调用 providers.clear(); lookupIterator = new LazyIterator(service, loader);//interface com.ssss.Hello,AppClassLoader } private ServiceLoader1(Class<S> svc, ClassLoader cl) {//service=interface com.ssss.Hello, cl=AppClassLoader。 service = Objects.requireNonNull(svc, "Service interface cannot be null");//interface com.ssss.Hello loader = (cl == null) ? ClassLoader.getSystemClassLoader() : cl;//AppClassLoader,getSystemClassLoader返回的也是appClassLoder,所以获取应用加载器可以线程获取也可以getSystemClassLoader()来获取。 acc = (System.getSecurityManager() != null) ? AccessController.getContext() : null;//null reload(); } private static void fail(Class<?> service, String msg, Throwable cause)throws ServiceConfigurationError { throw new ServiceConfigurationError(service.getName() + ": " + msg,cause); } private static void fail(Class<?> service, String msg) throws ServiceConfigurationError { throw new ServiceConfigurationError(service.getName() + ": " + msg); } private static void fail(Class<?> service, URL u, int line, String msg) throws ServiceConfigurationError { fail(service, u + ":" + line + ": " + msg); } private int parseLine(Class<?> service, URL u, BufferedReader r, int lc, List<String> names) throws IOException, ServiceConfigurationError { String ln = r.readLine();//一行 if (ln == null) { return -1;//-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);//添加实现类名字[com.ssss.impl.CHello, com.ssss.impl.JavaHello], } return lc + 1; } //u = file:\H:\2019326spring\蚂蚁课堂\0005-(每特教育&每特学院&蚂蚁课堂)-3期-并发编程专题-线程池原理分析\0005 //-(每特教育&每特学院&蚂蚁课堂)-3期-并发编程专题-线程池原理分析\上课代码\thread_day_day06_test\target //\classes\META-INF\services\com.ssss.Hello文件 private Iterator<String> parse(Class<?> service, URL u) throws ServiceConfigurationError { InputStream in = null; BufferedReader r = null; ArrayList<String> 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);//添加到names里面去。 } 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); } } return names.iterator(); } private class LazyIterator implements Iterator<S>//遍历实现类 { Class<S> service;//接口的Class ClassLoader loader;//app应用加载器 Enumeration<URL> configs = null;//配置文件的绝对路径 Iterator<String> pending = null;//所有实现类的集合 String nextName = null;//判断是否有下一个元素时候,就设置了下一个元素的名字了nextName private LazyIterator(Class<S> service, ClassLoader loader) { this.service = service;//interface com.ssss.Hello this.loader = loader;//AppClassLoader } private boolean hasNextService() {//是否有下一个实现类元素 if (nextName != null) { return true; } if (configs == null) {//初始化configs try { String fullName = PREFIX + service.getName();//文件路径:META-INF/services/com.ssss.Hello if (loader == null) configs = ClassLoader.getSystemResources(fullName); else configs = loader.getResources(fullName);//loader = AppClassLoader,加载META-INF/services/com.ssss.Hello资源 } catch (IOException x) { fail(service, "Error locating configuration files", x); } } while ((pending == null) || !pending.hasNext()) {//初始化pending if (!configs.hasMoreElements()) {//一个配置文件所有实现类遍历完之后,pending.hasNext()返回false,configs.hasMoreElements()返回false return false; } pending = parse(service, configs.nextElement());//pending = [com.ssss.impl.CHello, com.ssss.impl.JavaHello]集合,configs.nextElement()就是配置文件的绝对路径, } nextName = pending.next();//判断是否有下一个元素时候,就设置了下一个元素的名字了nextName,pending里面有一个游标,一直调用next方法时候游标加一,所以一直获取的是下一个元素。 return true; } private S nextService() {//下一个实现类 if (!hasNextService()) throw new NoSuchElementException(); String cn = nextName;//实现类名字com.ssss.impl.CHello nextName = null;//下一个名字置为null,再次获取下一个的时候重新设置值。 Class<?> c = null; try { c = Class.forName(cn, false, loader);//class com.ssss.impl.CHello } catch (ClassNotFoundException x) { fail(service, "Provider " + cn + " not found"); } if (!service.isAssignableFrom(c)) {//service = interface com.ssss.Hello,c = class com.ssss.impl.CHello. fail(service, "Provider " + cn + " not a subtype"); } try { S p = service.cast(c.newInstance());//p = com.ssss.impl.CHello@1324409e对象, providers.put(cn, p);//实现类的名字,实现类的对象放入缓存。{com.ssss.impl.CHello:com.ssss.impl.CHello@1324409e,com.ssss.impl.JavaHello:com.ssss.impl.JavaHello@246ae04d} return p;//返回实现类对象 } catch (Throwable x) { fail(service,"Provider " + cn + " could not be instantiated",x); } throw new Error(); // This cannot happen } public boolean hasNext() {//是否有下一个实现类元素 if (acc == null) {//权限判断 return hasNextService(); } else { PrivilegedAction<Boolean> action = new PrivilegedAction<Boolean>() { public Boolean run() { return hasNextService(); } }; return AccessController.doPrivileged(action, acc); } } public S next() {//下一个实现类 if (acc == null) { return nextService(); } else { PrivilegedAction<S> action = new PrivilegedAction<S>() { public S run() { return nextService(); } }; return AccessController.doPrivileged(action, acc); } } public void remove() { throw new UnsupportedOperationException(); } } //延迟加载:首先从缓存,配置文件加载之后加入缓存。 public Iterator<S> iterator() {//遍历方法。for循环时候先调用hasNext()在调用next()。 return new Iterator<S>() { 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(); return lookupIterator.next(); } public void remove() {//移除 throw new UnsupportedOperationException(); } }; } public static <S> ServiceLoader1<S> load(Class<S> service,ClassLoader loader){ return new ServiceLoader1<>(service, loader); } public static <S> ServiceLoader1<S> load(Class<S> service) {//service = interface com.ssss.Hello ClassLoader cl = Thread.currentThread().getContextClassLoader();//AppClassLoader,ServiceLoader类本身是boot加载器加载的,boot加载不到应用类路径下的类,所以要用app加载器。 return ServiceLoader1.load(service, cl); } public static <S> ServiceLoader1<S> loadInstalled(Class<S> service) { ClassLoader cl = ClassLoader.getSystemClassLoader();//系统加载器,app加载器 ClassLoader prev = null; while (cl != null) {//系统加载器为null,prev就是null。扩展加载器是null,prev就是系统加载器。否则prev就是扩展加载器。 prev = cl;//扩展加载器 cl = cl.getParent();//扩展加载器 } return ServiceLoader1.load(service, prev);//目的是为了加载jvm虚拟机里面的类,不是应用类路径下的类。 } public String toString() { return "java.util.ServiceLoader[" + service.getName() + "]"; } }