1 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 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138
| //这里能看出,META-INF/services/是两个文件夹,我在使用过程中,建成了一个,导致一直失败 private static final String PREFIX = "META-INF/services/"; private class LazyIterator implements Iterator<S> { private boolean hasNextService() { if (nextName != null) { return true; } // configs = URL = jar:file:/data/app/com.myapplication-1/base.apk!/META-INF/services/com.myapplication.spi.ISPIService if (configs == null) { try { //service的文件全路径名 String fullName = PREFIX + service.getName(); //loader == null就是系统SystemClassLoader.loader,否则自己的loader if (loader == null) configs = ClassLoader.getSystemResources(fullName); else configs = loader.getResources(fullName); } catch (IOException x) { } } // pending 就是fullName文件中的实现类 while ((pending == null) || !pending.hasNext()) { if (!configs.hasMoreElements()) { return false; } //解析service文件 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) { } try { S p = service.cast(c.newInstance()); providers.put(cn, p); return p; } catch (Throwable x) { x); } }
public boolean hasNext() { // Android-changed: do not use legacy security code /* 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() { // Android-changed: do not use legacy security code /* 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(); }
} private LinkedHashMap<String,S> providers = new LinkedHashMap<>(); //读文件啊,解析文件内容,按行截取,放到list里,首行排到第一位0,顺序依次 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 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); } if (!providers.containsKey(ln) && !names.contains(ln)) names.add(ln); } return lc + 1; }
|