S
ervice P
rovider I
nterface
提供接口,可替换组件实现,插件扩展,服务发现机制
META-INF/services/接口全限定名
文件中指定实现类,文件可以有多行每行一个实现类
ServiceLoader源码实现
ServiceLoader设计成一个迭代结构,即可以加载同一接口的多个实现
- 调用load只是构建了迭代器,并且延迟加载,真正遍历时才加载
- 加载到类名字符串后采取forName获取类,反射newInstance获取实例
- 缓存机制,加载过一次就把实例缓存起来,再次加载直接读缓存
ServiceLoader.java1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59
| public final class ServiceLoader<S> implements Iterable<S> { private static final String PREFIX = "META-INF/services/";
private final Class<S> service; private final ClassLoader loader; private final AccessControlContext acc; private LinkedHashMap<String,S> providers = new LinkedHashMap<>(); private LazyIterator lookupIterator;
public static <S> ServiceLoader<S> load(Class<S> service) { ClassLoader cl = Thread.currentThread().getContextClassLoader(); return ServiceLoader.load(service, cl); } public static <S> ServiceLoader<S> load(Class<S> service, ClassLoader loader) { return new ServiceLoader<>(service, loader); }
private ServiceLoader(Class<S> svc, 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(); } public void reload() { providers.clear(); lookupIterator = new LazyIterator(service, loader); }
public Iterator<S> iterator() { 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(); } }; } }
|
查找细节
ServiceLoader.java1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61
| private class LazyIterator implements Iterator<S> { Class<S> service; Enumeration<URL> configs = null; private boolean hasNextService() { 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; }
private S nextService() { if (!hasNextService()) throw new NoSuchElementException(); 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); return p; } catch (Throwable x) { fail(service, "Provider " + cn + " could not be instantiated",x); } throw new Error(); } }
|
SPI应用
JDBC
DriverManager.java1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53
| public class DriverManager { static { loadInitialDrivers(); println("JDBC DriverManager initialized"); }
private static void loadInitialDrivers() { String drivers; try { drivers = AccessController.doPrivileged(new PrivilegedAction<String>() { public String run() { return System.getProperty("jdbc.drivers"); } }); } catch (Exception ex) { drivers = null; }
AccessController.doPrivileged(new PrivilegedAction<Void>() { public Void run() { ServiceLoader<Driver> loadedDrivers = ServiceLoader.load(Driver.class); Iterator<Driver> driversIterator = loadedDrivers.iterator();
try{ while(driversIterator.hasNext()) { driversIterator.next(); } } catch(Throwable t) { } return null; } });
String[] driversList = drivers.split(":"); println("number of Drivers:" + driversList.length); for (String aDriver : driversList) { try { println("DriverManager.Initialize: loading " + aDriver); Class.forName(aDriver, true, ClassLoader.getSystemClassLoader()); } catch (Exception ex) { println("DriverManager.Initialize: load failed: " + ex); } } } }
|
Mysql的驱动器包为mysql-connector-java.jar
内部包含META-INF/services/java.sql.Driver
文件
文件内容为com.mysql.cj.jdbc.Driver
SPI机制进行类加载,会触发驱动类下静态初始化块,把驱动注册到JDBC的DriverManager中
Driver.java1 2 3 4 5 6 7 8 9 10 11 12 13
| public class Driver extends NonRegisteringDriver implements java.sql.Driver { static { try { java.sql.DriverManager.registerDriver(new Driver()); } catch (SQLException E) { throw new RuntimeException("Can't register driver!"); } }
public Driver() throws SQLException { } }
|
整体流程
- JDBC加载DriverManager
- DriverManager静态初始化块寻找Driver触发SPI
- SPI加载到Mysql的Driver类
- Driver静态初始化块内创建实例,注册到DriverManager