我想在Java应用程序中实现动态插件功能。理想的情况是:
Plugin
等方法定义接口getCapabilities()
。pluginX.jar
,其中包含一个实现PluginXImpl
(可能还有其他一些)的类Plugin
。pluginX.jar
放在特殊目录中或设置指向它的配置参数。用户不一定必须在其类路径中包含pluginX.jar
。PluginXImpl
(可能通过JAR清单,可能通过反射)并将其添加到注册表中。PluginXImpl
的实例,例如,通过调用getPluginWithCapabilities("X")
之类的方法。用户不一定必须知道插件的名称。我有一种感觉我应该可以用peaberry做到这一点,但我无法理解文档。我花了一些时间学习Guice,所以我的首选答案不是“使用Spring Dynamic Modules。”
有人可以简单介绍一下如何使用Guice / peaberry,OSGi或纯Java进行此操作吗?
答案 0 :(得分:17)
使用普通Java意味着这很简单:
由于您不希望用户在启动应用程序之前配置类路径,因此我首先要创建一个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)来获取服务加载器您的插件接口并在其上调用iterator()以获取所有已配置的插件实现的实例。
你仍然需要提供自己的包装来过滤插件功能,但我认为这不应该太麻烦。
答案 1 :(得分:1)
如果你想在运行时更换插件,OSGI会没问题。用于24/7环境中的错误修正。我和OSGI玩了一段时间,但是花了太多时间,因为这不是一个要求,如果你删除一个包,你需要一个计划b。
我的谦虚解决方案是,提供一个包含插件描述符类的类名的属性文件,让服务器调用它们进行注册(包括查询它们的功能)。
这显然不是最理想的,但我迫不及待地想阅读接受的答案。
答案 2 :(得分:1)
您是否有机会利用Service Provider Interface?
答案 3 :(得分:1)
使用Guice实现插件的最佳方法是使用Multibindings。链接页面详细介绍了如何使用多重绑定来托管插件。
答案 4 :(得分:0)
如果您知道这一点,请道歉,但请查看Class的forName
方法。它至少在JDBC中用于按类名动态加载DBMS特定的驱动程序类运行时。
然后我想枚举目录中的所有类/ jar文件,加载每个文件并定义一个静态方法getCapabilities()
(或您选择的任何名称)的接口并不难功能/描述,以及对您的系统有意义的任何术语和格式。