如何在实现定义接口的类路径中发现运行时的类?
ServiceLoader非常适合(我认为,我还没有使用它),但我需要在Java 1.5中使用它.
Java 1.5中没有内置任何内容.我自己实现了; 它并不太复杂.但是,当我们升级到Java 6时,我将不得不通过调用替换对我的实现的调用ServiceLoader
.我可以在应用程序和加载器之间定义一个小桥梁,但我只在几个地方使用它,而包装器本身也是ServiceLoader的一个很好的候选者.
这是核心理念:
publicIterableload(Classifc) throws Exception { ClassLoader ldr = Thread.currentThread().getContextClassLoader(); Enumeratione = ldr.getResources("META-INF/services/" + ifc.getName()); Collection services = new ArrayList(); 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.
javax.imageio.spi.ServiceRegistry
与以前的Java版本等效.它从Java 1.4开始就可用.
它看起来不像一般的实用类,但确实如此.它甚至比ServiceLoader
它更强大,因为它允许对返回的提供程序的顺序进行一些控制并直接访问注册表.
请参阅http://docs.oracle.com/javase/7/docs/api/index.html?javax/imageio/spi/ServiceRegistry.html