如何使java ServiceLoader在NetBeans 6.9模块应用程序中工作

时间:2010-06-29 16:05:53

标签: java netbeans serviceloader

我在NetBeans模块应用程序中使用java ServiceLoader时遇到了麻烦。这是我正在尝试做的事情(它在Eclipse中的普通java应用程序中工作):

我有一个interface.jar,它声明了接口。我有implements.jar,它有几个这个接口的实现,都在spi / META-INF / services / my.package.name.MyInteface文件中指定(该文件位于implementation.jar中)。

我还有一个类ImplementationHandler(在另一个handler.jar中),它有以下方法来加载所有实现:

private static List<MyInterface<?>> loadAllImplementations() {
    List<MyInterface<?>> foundImplementations = Lists.newArrayList();
    try {
        for (MyInterface implementation : ServiceLoader.load(MyInterface.class)) {
            foundImplementations.add(implementation);
        }
    } catch (ServiceConfigurationError error) {
        system.out.println("Exception happened");
    }
    return foundImplementations;
}

此代码返回Eclipse正常应用程序中的所有实现(foundImplementations.size()&gt; 0)。

但是在NetBeans下,它找不到任何内容(foundImplementations.size()== 0)。

更多详情:
我有一个NetBeans模块应用程序的源代码(开源,不是我编写的),我需要通过使用一些MyInterface实现来扩展它。 interface.jar,implements.jar和handler.jar是在Eclipse中创建的,它们是另一个应用程序的一部分。

在NetBeans中,我打开了需要使用新功能的模块,我将所有3个jars添加为外部库(NetBeans将它们复制到ext文件夹中,我不想要,但我不能做任何事情关于 - 我希望他们在另一个myext文件夹中,但这是另一个故事)。然后我重建了所有内容并尝试使用我的一个实现,但是没有找到...获得实现的代码在ImplementationHandler类中,看起来像:

public static final <T> MyInteface<T> getByName(String name) {
    for (MyInteface implementation : loadAllImplementations()) {
        if (implementation.getName().equals(name)) {
            return implementation;
        }
    }

    throw new IllegalArgumentException("Unable to find MyInterface class for: " + name);
}

我得到了异常“无法找到myInteface类:myImplementationName”...

我对NetBeans的了解非常有限,我想知道还有什么需要做的才能让它工作吗?

3 个答案:

答案 0 :(得分:2)

为了工作,你必须让Netbeans在META-INF中创建这个服务子文件夹。这很容易,但信息很容易获取。

要向META-INF添加内容,您需要在src /(源目录[spi?])文件夹中创建此名称的文件夹。在这种情况下,您还需要services文件夹,并在其中创建一个与服务接口具有相同完全限定名称的文本文件。最后你应该有这个结构:src / META-INF / services / my.package.MyInterface。

最后,这个[my.package.MyInterface]文件的内容应列出所有实现类(每行一个)。

通过此设置,Netbeans将在构建应用程序时创建相应的jar。

看看this ServiceLoader示例。这是一个完整的例子,虽然它没有解释我刚刚描述的Netbeans集成。

答案 1 :(得分:0)

ServiceLoader.load(Class)使用当前线程的上下文类加载器来加载所有实现。在您的情况下,您的jar文件(implementation.jar)中的实现类可能不在该类加载器的类路径中。

您可能需要尝试不同的方法:

  • 您可能需要在netbeans模块的类路径中包含所有jar,或者
  • 您可能需要创建一个类加载器(可能是在其类路径中具有这些jar的URLClassLoader)并使用ServiceLoader.load(Class, ClassLoader)并传递该类加载器。
  • 您可以尝试另一个选项,但我不确定:jar文件规范允许您指定Class-Path清单属性,您可以在其中添加'implementation.jar'条目。更多详情here

很可能,handler.jar和implements.jar不是由同一个类加载器加载的。另外,您可能需要查看文件到达ext文件夹的原因。

希望这有帮助。

编辑:

  • 还尝试调用使用System类加载器的ServiceLoader.load(Class, null)(启动应用程序的那个)。可能该类加载器可能能够在ext目录中的jar中找到类。

答案 2 :(得分:0)

我放弃了,用JSPF替换了ClassLoader。这是开箱即用的,我不需要知道第三方程序的内部结构,编写为NetBeans模块以及它如何影响类加载器的类路径。