我在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的了解非常有限,我想知道还有什么需要做的才能让它工作吗?
答案 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)中的实现类可能不在该类加载器的类路径中。
您可能需要尝试不同的方法:
ServiceLoader.load(Class, ClassLoader)
并传递该类加载器。很可能,handler.jar和implements.jar不是由同一个类加载器加载的。另外,您可能需要查看文件到达ext文件夹的原因。
希望这有帮助。
编辑:
ServiceLoader.load(Class, null)
(启动应用程序的那个)。可能该类加载器可能能够在ext目录中的jar中找到类。答案 2 :(得分:0)
我放弃了,用JSPF替换了ClassLoader。这是开箱即用的,我不需要知道第三方程序的内部结构,编写为NetBeans模块以及它如何影响类加载器的类路径。