如何在运行时在实现已定义接口的类路径中发现类?
ServiceLoader非常适合(我认为,我还没有使用过),但是我需要在Java 1.5中做到。
Java 1.5没有为此内置任何功能。我自己实现了它;不太复杂。但是,当我们升级到Java 6时,必须将对实现的调用替换为对的调用ServiceLoader。我本可以在应用程序和加载器之间定义一个小桥梁,但是我只在少数几个地方使用它,而包装器本身将是ServiceLoader的理想选择。
ServiceLoader
这是核心思想:
public <S> Iterable<S> load(Class<S> ifc) throws Exception { ClassLoader ldr = Thread.currentThread().getContextClassLoader(); Enumeration<URL> e = ldr.getResources("META-INF/services/" + ifc.getName()); Collection<S> services = new ArrayList<S>(); while (e.hasMoreElements()) { URL url = e.nextElement(); InputStream is = url.openStream(); try { BufferedReader r = new BufferedReader(new InputStreamReader(is, "UTF-8")); while (true) { String line = r.readLine(); if (line == null) break; int comment = line.indexOf('#'); if (comment >= 0) line = line.substring(0, comment); String name = line.trim(); if (name.length() == 0) continue; Class<?> clz = Class.forName(name, true, ldr); Class<? extends S> impl = clz.asSubclass(ifc); Constructor<? extends S> ctor = impl.getConstructor(); S svc = ctor.newInstance(); services.add(svc); } } finally { is.close(); } } return services; }
更好的异常处理留给读者练习。同样,可以对方法进行参数化以接受调用者选择的ClassLoader。