public class ProviderInterceptorFactory { //經過ExtensionLoader來加載interceptor private static List<ProviderInterceptor> interceptors = ExtensionLoader .getExtensionList(ProviderInterceptor.class); // 也能夠手動調用這個方法來註冊 public static boolean registerInterceptor(ProviderInterceptor providerContextInterceptor) { if (!interceptors.contains(providerContextInterceptor)) { return interceptors.add(providerContextInterceptor); } return false; } public static boolean unregisterInterceptor(ProviderInterceptor providerContextInterceptor) { return interceptors.remove(providerContextInterceptor); } public static List<ProviderInterceptor> getInterceptors() { return interceptors; } }
public final class ExtensionLoader { //使用map來存儲接口對應的實現,若是map中沒有,則經過serviceloader來加載 private static Map<Class<?>, Object> extensionMap = new ConcurrentHashMap<Class<?>, Object>(); private static Map<Class<?>, List<?>> extensionListMap = new ConcurrentHashMap<Class<?>, List<?>>(); private ExtensionLoader() { } public static <T> T getExtension(Class<T> clazz) { T extension = (T) extensionMap.get(clazz); if (extension == null) { extension = newExtension(clazz); if (extension != null) { extensionMap.put(clazz, extension); } } return extension; } public static <T> List<T> getExtensionList(Class<T> clazz) { List<T> extensions = (List<T>) extensionListMap.get(clazz); if (extensions == null) { extensions = newExtensionList(clazz); if (!extensions.isEmpty()) { extensionListMap.put(clazz, extensions); } } return extensions; } public static <T> T newExtension(Class<T> clazz) { // here ServiceLoader<T> serviceLoader = ServiceLoader.load(clazz); for (T service : serviceLoader) { return service; } return null; } public static <T> List<T> newExtensionList(Class<T> clazz) { ServiceLoader<T> serviceLoader = ServiceLoader.load(clazz); List<T> extensions = new ArrayList<T>(); for (T service : serviceLoader) { extensions.add(service); } return extensions; } }
重點就是ServiceLoader.load緩存
// ServiceLoader 實現了Iterable public final class ServiceLoader<S> implements Iterable<S> { //目錄路徑 private static final String PREFIX = "META-INF/services/"; // 正在加載的類或接口 private Class<S> service; //用來實例化的classloader private ClassLoader loader; // 按實例化的順序緩存實現類 private LinkedHashMap<String,S> providers = new LinkedHashMap<>(); //ServiceLoader自定義的一個內部類,主要實現了懶加載 private LazyIterator lookupIterator; public void reload() { providers.clear(); lookupIterator = new LazyIterator(service, loader); } private ServiceLoader(Class<S> svc, ClassLoader cl) { service = svc; loader = cl; 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); } //解析文件,將文件中的name放到list中 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; } 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); } // 加載過的不放在這個list裏 if (!providers.containsKey(ln) && !names.contains(ln)) names.add(ln); } return lc + 1; } 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); } 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; ClassLoader loader; Enumeration<URL> configs = null; Iterator<String> pending = null; String nextName = null; private LazyIterator(Class<S> service, ClassLoader loader) { this.service = service; this.loader = loader; } public boolean hasNext() { 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; } public S next() { if (!hasNext()) { 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 { //在next到某個實現類時,才真正的加載實例 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(); // This cannot happen } public void remove() { throw new UnsupportedOperationException(); } } 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(); } }; } public static <S> ServiceLoader<S> load(Class<S> service, ClassLoader loader) { return new ServiceLoader<>(service, loader); } public static <S> ServiceLoader<S> load(Class<S> service) { ClassLoader cl = Thread.currentThread().getContextClassLoader(); return ServiceLoader.load(service, cl); } public static <S> ServiceLoader<S> loadInstalled(Class<S> service) { ClassLoader cl = ClassLoader.getSystemClassLoader(); ClassLoader prev = null; while (cl != null) { prev = cl; cl = cl.getParent(); } return ServiceLoader.load(service, prev); } }