如何创建可插拔的Java程序?

42
我希望创建一个可以通过插件扩展的Java程序。我该如何做,应该在哪里寻找?
我有一组接口,插件必须实现它们,并且应该在一个jar包中。程序应该监视相对于程序的文件夹中的新jar包,并以某种方式注册它们。
尽管我喜欢Eclipse RCP,但我认为它对我的简单需求来说过于复杂。
Spring也是同样的情况,但既然我本来就要看它,那么我也可以试试。
但是,我更希望找到一种能够尽可能简单地创建自己的插件“框架”的方法。

可能是使用Java构建插件系统的最佳方法的重复问题。这个问题发布得更早,但另一个问题最终变得更受欢迎。 - Ciro Santilli OurBigBook.com
6个回答

50

我以前为自己编写的软件完成了这个功能,非常方便。我首先创建了一个接口,所有“插件”类都需要实现该接口。然后我使用Java ClassLoader加载这些类并创建它们的实例。

你可以按照以下方式进行操作:

File dir = new File("put path to classes you want to load here");
URL loadPath = dir.toURI().toURL();
URL[] classUrl = new URL[]{loadPath};

ClassLoader cl = new URLClassLoader(classUrl);

Class loadedClass = cl.loadClass("classname"); // must be in package.class name format
那么现在已经加载了这个类,接下来需要创建一个它的实例,假设接口名称为MyModule。
MyModule modInstance = (MyModule)loadedClass.newInstance();

我知道我有点晚了,但如果你想循环遍历目录中的所有给定类并加载它们,该怎么办?有没有地方可以看到一个可行的实现和在线代码?除此之外,我理解你们大多数人的代码,它非常简单,谢谢!+1 - Cody Richardson
1
@CodyRichardson 在 http://www.knowbase.org/viewtopic.php?id=31 上有一个简单实现的完整示例;它使用了 Java 8 和 Gradle 4。 - Alexiy
@Alexiy 谢谢你提供的链接,它帮了我很多,基本上包含了我所需要的一切。起初有点复杂(主要是 lambda 表达式),但那只是因为我是 Java 新手 :) 我看了几遍后就理解得更清楚了。非常感谢你! - Cody Richardson
1
我的上面的链接已经不存在了,教程现在托管在这里 - https://alexiyorlov.github.io/tutorials/java-plugins.html - Alexiy
我尝试了很多种变体,但出现的情况是:我无法将我的类强制转换为接口,因为这会引发ClassCastException异常。Java 1.8或更高版本存在问题吗? - Brain

18

了解 OSGi

一方面,OSGi提供各种基础设施来管理、启动和处理模块化软件组件的各种事情。另一方面,它可能过于笨重,不适合您的需求。

顺便说一下,Eclipse使用OSGi来管理其插件。


1
+1 for OSGi。我认为它在简单的ClassLoader技巧(这将让你不得不重新发明很多轮子)和Eclipse RCP(对于不太复杂的任务而言是一个庞大的框架)之间找到了合适的尺寸。 - Leonel

16

我建议您仔细研究Java服务提供者(SPI)API。它提供了一个简单的系统,用于查找所有在类路径上的Jars中公开自己作为实现特定服务的类。 我过去在插件系统中使用它,并取得了很大的成功。


2
请注意,sun.misc.Service类已被java.util.ServiceLoader类所代替。 - Kevin Wong

6
尽管我支持已接受的解决方案,但如果需要基本的插件支持(这在大多数情况下都是如此),还有Java插件框架(JPF),虽然缺乏适当的文档,但它是一个非常整洁的插件框架实现。它易于部署,并且 - 当您通过类加载怪癖时 - 非常容易开发。对上述评论的一点提醒是要注意,插件目录下的插件加载路径必须按照完整的类路径命名,并在普通包路径中命名其类文件路径。例如:
plugins
`-com.my.package.plugins
  `-com
    `-my
      `-package
        `-plugins
          |- Class1.class
          `- Class2.class

4
在自行开发的类加载器方法中: 虽然这是学习类加载器的好方法,但有一种被称为“类加载器地狱”的东西,大多数人在处理较大项目时都会遇到。冲突的类很容易引入,但难以解决。
Eclipse多年前转向OSGi也有充分的理由。 因此,如果不仅仅是个人项目,请认真考虑使用OSGi。它值得一看。 您将学习有关类加载器及新兴技术标准的知识。

OSGi 很好,但对于在启动时加载然后不再改变的小插件来说,它太大且过于复杂。 - Enerccio

1
你考虑过在Eclipse的Rich Client Platform基础上构建,然后暴露Eclipse扩展框架吗?
另外,根据你的需求,Spring Framework可能会对你想做的事情以及其他一些事情有所帮助:http://www.springframework.org/

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