ServiceLoader<Driver> drivers = ServiceLoader.load(Driver.class); Iterator<Driver> iterator = drivers.iterator(); while (iterator.hasNext()){ Driver next = iterator.next(); System.out.println(next.getClass()); }
构造ServiceLoader,这个比较简单
//1,传入Driver.class public static <S> ServiceLoader<S> load(Class<S> service) { //2,获取当前线程的类加载器 ClassLoader cl = Thread.currentThread().getContextClassLoader(); //3,构造ServiceLoader实例 return ServiceLoader.load(service, cl); }
private ServiceLoader(Class<S> svc, ClassLoader cl) { service = Objects.requireNonNull(svc, "Service interface cannot be null"); //dk 线程上线文为空,则用系统类加载器 loader = (cl == null) ? ClassLoader.getSystemClassLoader() : cl; acc = (System.getSecurityManager() != null) ? AccessController.getContext() : null; reload(); }
public void reload() { providers.clear(); //dk 构造一个懒加载迭代器 lookupIterator = new LazyIterator(service, loader); }
==============hasNext解析==============
public boolean hasNext() { if (knownProviders.hasNext()) return true; //dk 执行这行 return lookupIterator.hasNext(); }
public boolean hasNext() { if (acc == null) { //dk 执行这行 return hasNextService(); } else { PrivilegedAction<Boolean> action = new PrivilegedAction<Boolean>() { public Boolean run() { return hasNextService(); } }; return AccessController.doPrivileged(action, acc); } }
private boolean hasNextService() { if (nextName != null) { return true; } if (configs == null) { try { //dk 这行非常关键 //dk fullName=META-INF/services/java.sql.Driver String fullName = PREFIX + service.getName(); if (loader == null) configs = ClassLoader.getSystemResources(fullName); else //dk 扫描所有类路径下的有META-INF/services的配置 configs = 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()); } //dk 获取到spi路径下的类名,返回true nextName = pending.next(); return true; }
private S nextService() { if (!hasNextService()) throw new NoSuchElementException(); String cn = nextName; nextName = null; Class<?> c = null; try { //dk 反射执行spi里面的类,注意第三个参数,如果当前类加载器加载不到,则用应用类加载器加载 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()); //dk 放入缓存中,提高效率 providers.put(cn, p); return p; } catch (Throwable x) { fail(service, "Provider " + cn + " could not be instantiated", x); } throw new Error(); // This cannot happen }
====================next=====================
Driver next = iterator.next();
public S next() { if (knownProviders.hasNext()) return knownProviders.next().getValue(); return lookupIterator.next(); }
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); } }
private S nextService() { //dk 返回false if (!hasNextService()) throw new NoSuchElementException(); String cn = nextName; nextName = null; Class<?> c = null; try { //dk 反射加载到jvm里面 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()); //dk 方法缓存中 providers.put(cn, p); return p; } catch (Throwable x) { fail(service, "Provider " + cn + " could not be instantiated", x); } throw new Error(); // This cannot happen }
private boolean hasNextService() { //spi加载类名不为空,返回true if (nextName != null) { return true; } if (configs == null) { try { String fullName = PREFIX + service.getName(); if (loader == null) configs = ClassLoader.getSystemResources(fullName); else configs = 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; }