尝试pigeon拦截器的时候,发现加载自定义拦截器的时候是通过spi serviceloader加载的,学习一波spi。
某个接口,实现有多种,spi能够为某个接口提供具体的实现类。先看下在spi机制下怎么在pigeon中自定义拦截器:
//自定义了一个拦截器,实现了pigeon提供了拦截器接口public class BusinessProviderInterceptor implements ProviderInterceptor { @Override public void preInvoke(ProviderContext providerContext) { LogTagContext.setLogTag("mobileno", "12345678"); } @Override public void postInvoke(ProviderContext providerContext) { }
META-INF/services下创立一个以接口命名的文件,文件里按行排列具体的实现类;文件里内容如下:
xxx.xxx.xxx.xxx.BusinessProviderInterceptor#other selfinterceptor which implement ProviderInterceptor
以上,能够在pigeon中实现自定义拦截器。
pigeon是如何加载实例化这些拦截器的,具体如下:
//providerinterceptor的执行在BuinessProcessFilter里,ProviderProcessInterceptorFactory在废除,新的是ProviderInterceptorFactoryList<ProviderProcessInterceptor> interceptors = ProviderProcessInterceptorFactory.getInterceptors();for (ProviderProcessInterceptor interceptor : interceptors) { interceptor.preInvoke(request);}List<ProviderInterceptor> contextInterceptors = ProviderInterceptorFactory.getInterceptors();for (ProviderInterceptor interceptor : contextInterceptors) { interceptor
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 实现了Iterablepublic 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); }}