Java 1.5中是否有类似于ServiceLoader的东西?

15

如何在类路径中查找运行时实现了已定义接口的类?

ServiceLoader 适用于此需求(我认为,尽管我没有使用过),但我需要在 Java 1.5 中进行。

6个回答

19

Java 1.5没有内置此功能,我自己实现了它,不太复杂。但是,当我们升级到Java 6时,我将不得不用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。


6

1

不幸的是,

Java 1.5 中没有为此构建任何内容...

这只是部分真相。

实际上,存在非标准的 sun.misc.Service

http://www.docjar.com/docs/api/sun/misc/Service.html

小心,它不是J2SE API的一部分! 这是Sun JDK的非标准部分。 所以如果你使用JRockit,你不能依赖它。


1

ServiceLoader非常基础,并且在JDK中从1.3版开始(非正式地)使用。 ServiceLoader最终成为了一等公民。它只是查找名为您的接口的资源文件,该文件基本上捆绑在库jar的META-INF目录中。

该文件包含要加载的类的名称。

因此,您将拥有一个名为:

META-INF/services/com.example.your.interface

在其中有一行代码:com.you.your.interfaceImpl。

与ServiceLoader相比,我更喜欢Netbeans Lookup。它可以与1.5(或1.4)一起使用。

开箱即用,它所做的与ServiceLoader完全相同,并且非常容易使用。但是它提供了更多的灵活性。

这里是一个链接:http://openide.netbeans.org/lookup/

这篇文章介绍了ServiceLoader,但是在底部提到了Netbeans Lookup: http://weblogs.java.net/blog/timboudreau/archive/2008/08/simple_dependen.html


1
这是一个老问题,但另一种选择是使用包级别注释。 请参阅我的答案:查找实现接口的Java类 包级别注释是在package-info.java类中的注释。
JAXB使用它来代替服务加载器。我认为它比服务加载器更灵活。

0

没有可靠的方法来知道类路径中有哪些类。根据其文档,ServiceLoader依赖于外部文件来告诉它要加载哪些类;您可能希望采取相同的做法。基本思路是创建一个名为要加载类的文件,然后使用反射来实例化它/它们。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接