问题描述
如何在实现定义接口的类路径中发现运行时的类?
How do I discover classes at runtime in the classpath which implements a defined interface?
ServiceLoader非常适合(我想,我还没有使用它),但是我需要在Java 1.5中完成它。
ServiceLoader suits well (I think, I haven't used it), but I need do it in Java 1.5.
推荐答案
Java 1.5中没有内置任何内容。我自己实施了;这不是太复杂。但是,当我们升级到Java 6时,我将不得不通过调用 ServiceLoader
来替换对我的实现的调用。我可以在应用程序和加载器之间定义一个小桥梁,但我只在几个地方使用它,并且包装器本身将是ServiceLoader的一个很好的候选者。
There's nothing built into Java 1.5 for this. I implemented it myself; it's not too complicated. However, when we upgrade to Java 6, I will have to replace calls to my implementation with calls to ServiceLoader
. I could have defined a little bridge between the app and the loader, but I only use it in a few places, and the wrapper itself would be a good candidate for a 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。
Better exception handling is left as an exercise for the reader. Also, the method could be parameterized to accept a ClassLoader of the caller's choosing.
这篇关于类似于Java 1.5中的ServiceLoader吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!