2010-01-20 52 views
18

我想在Java应用程序中实现动态插件功能。理想情况下:在Java中实现动态插件

  • 该应用程序将定义一个接口Plugin与方法如getCapabilities()
  • 插件将是JAR pluginX.jar,其中包含PluginXImpl类实现Plugin(也可能包括其他一些)。
  • 用户将pluginX.jar放在一个特殊的目录中或设置一个指向它的配置参数。用户不一定必须在其类路径中包含pluginX.jar
  • 应用程序会找到PluginXImpl(也许通过JAR清单,也许通过反射)并将其添加到注册表中。
  • 客户端可以获得PluginXImpl的实例,例如通过调用getPluginWithCapabilities("X")等方法。用户不一定必须知道插件的名称。

我有一种感觉,我应该能够做到这一点与peaberry,但我不能任何意义的文件。我已经投入了一些时间学习Guice,所以我的首选答案不会是“使用Spring Dynamic Modules”。

有人可以给我一个简单的想法,如何去做这个使用Guice/peaberry,OSGi,或只是普通的Java?

+0

Peaberry和Spring DM都是OSGi上的图层。 OSGi似乎做了你想做的事情(概念上),但它会做'OSGi-way',并且不会映射到你的确切过程,所以建议谷歌的一些OSGi教程。 – SteveD 2010-01-20 21:41:19

+1

OSGi看起来比peaberry复杂一百倍。任何链接到好的教程? – 2010-01-20 21:48:20

回答

17

这其实是很容易使用普通的Java意味着:

既然你不想让用户启动应用程序之前配置classpath中,我将首先创建一个URLClassLoader的使用URL的数组中的文件你的插件目录。使用File.listFiles查找所有插件jar,然后使用File.toURI()。toURL()获取每个文件的URL。您应该将系统类加载器(ClassLoader.getSystemClassLoader())作为父类传递给您的URLClassLoader。

如果插件jar包含META-INF/services中的配置文件,如java.util.ServiceLoader的API文档中所述,那么现在可以使用ServiceLoader.load(Plugin.class,myUrlClassLoader)来禁止服务加载器为你的Plugin接口调用iterator()来获取所有配置的Plugin实现的实例。

你仍然需要提供你自己的包装来过滤插件的功能,但是这不应该太麻烦,我想。

+0

您能否详细解释一下这个问题? – stacker 2010-01-20 21:45:14

+1

除非你有更详细的问题,否则不要。 – jarnbjo 2010-01-20 22:11:13

+0

@jarnbjo:完全有效!谢谢!我仍然有兴趣看到一个peaberry或OSGi解决方案... – 2010-01-20 23:20:41

0

如果您知道这一点,请道歉,但请查看ClassforName方法。它至少在JDBC中用于通过类名动态加载DBMS特定的驱动程序类运行时。

然后我想枚举目录中的所有类/ jar文件并加载其中的每个文件并且为静态方法getCapabilities()(或您选择的任何名称)定义一个接口以返回其功能/描述并不困难无论使用哪种术语和格式对您的系统都有意义。

+0

@ Bandi-T:我在回复中添加了上面的一些要求。我不想使用'getPluginInstance(“org.example.PluginXImpl”)''或者必须在classpath中有plugins目录。 – 2010-01-20 20:59:09

+0

@Chris Conway:那么我很抱歉,那超出了我的想法,我在Java中并没有太高级的先进性。 – 2010-01-20 21:09:56

1

如果您想在运行期间替换插件,OSGI会很好。在24/7环境中进行错误修复。我和OSGI玩了一段时间,但花了太多时间,因为这不是一个要求,如果你删除一个捆绑包,你需要一个计划。

我的卑微的解决方案是,提供一个带有插件描述符类类名的属性文件,并让服务器调用它们来注册(包括查询它们的功能)。

这显然不是最理想的,但我迫不及待地想阅读接受的答案。

1

与Guice实现插件的最佳方式是Multibindings。链接页面将详细介绍如何使用多重绑定来托管插件。

+1

“请注意,在系统运行时,此机制无法加载或卸载插件。”在我看来,多重绑定需要插件JAR位于类路径中,并且用户需要在配置文件中指定模块类。也许你可以使用ClassLoader动态加载插件目录中的JAR,但是你必须使用类似于Service加载器的东西来自动查找模块。 – 2010-01-21 14:05:14