代码之家  ›  专栏  ›  技术社区  ›  Telcontar

类似于Java 1.5中的Service EoLoad吗?

  •  15
  • Telcontar  · 技术社区  · 16 年前

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

    Service LooDad非常适合(我想,我还没有使用它),但是我需要在Java 1.5中完成。

    7 回复  |  直到 10 年前
        1
  •  18
  •   erickson    16 年前

    在Java 1.5中没有任何东西。我自己实现的,并不太复杂。但是,当我们升级到Java 6时,我将不得不用调用来替换对实现的调用。 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;
    }
    

    更好的异常处理留给读者作为练习。此外,该方法还可以参数化以接受调用方选择的类加载器。

        2
  •  5
  •   Brad Mace Mike King    10 年前

    javax.imageio.spi.ServiceRegistry 与以前的Java版本相当。它可以从Java 1.4获得。

    它看起来不像一个通用的实用程序类,但它是。它甚至比 ServiceLoader ,因为它允许对返回的提供程序的顺序进行一些控制并直接访问注册表。

    http://docs.oracle.com/javase/7/docs/api/index.html?javax/imageio/spi/ServiceRegistry.html

        3
  •  1
  •   Will Hartung    16 年前

    ServiceLoader非常基础,从1.3开始就在JDK中使用(非正式)。ServiceLoader最终成为了一流的公民。它只是为您的接口寻找一个名为的资源文件,它基本上捆绑在库JAR的META-INF目录中。

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

    所以,你会有一个文件名为:

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

    里面只有一行:com.you.your.interfaceimpl。

    代替ServiceLoader,我喜欢NetBeans查找。它适用于1.5(可能是1.4)。

    开箱即用,它与ServiceLoader做的事情完全相同,而且使用起来很简单。但它提供了更多的灵活性。

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

    这里有一篇关于ServiceLoader的文章,但在底部提到了NetBeans查找: http://weblogs.java.net/blog/timboudreau/archive/2008/08/simple_dependen.html

        4
  •  1
  •   Community rohancragg    7 年前

    这是个老问题,但另一个选择是 包级批注 . 请看我的答案: Find Java classes implementing an interface

    包级注释是package-info.java类中的注释。

    JAXB使用这个而不是服务加载程序。我还认为它比服务加载器更灵活。

        5
  •  1
  •   akjoshi HCP    12 年前

    不幸的是,

    没有什么内置到Java 1.5…

    只是真理的一部分。

    有不标准的 sun.misc.Service 周围。

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

    注意,它不是标准J2SE API的一部分! 它是Sun JDK的非标准部件。 所以你不能依赖它,如果你使用,比如, JRockit .

        6
  •  0
  •   Michael Myers KitsuneYMG    16 年前

    没有可靠的方法来知道类路径中有哪些类。根据它 documentation 服务加载器依赖外部文件来告诉它要加载哪些类;您可能也希望这样做。基本思想是使用一个名为要加载的类的文件,然后使用反射来实例化它/它们。

        7
  •  -1
  •   David Scurrah    16 年前

    您是否想过使用OSGi框架?