2

我想添加一个从外部向我的程序添加更多“命令”的系统。

基本上,与我的 jar(可执行文件)位于同一目录中的文件夹可以具有不同数量的“扩展”

每个“扩展”都是一个 .class 文件,它扩展了某个抽象类,该抽象类具有为识别等定义的方法。

但是,我似乎无法确定是否可以.class从我的主包外部控制这些文件。

这可能吗?如果有怎么办?如果没有,我可以尝试其他选择吗?

谢谢!

4

4 回答 4

3

据我了解你。你想建立一个插件系统。如果是这样,您应该考虑 java 服务提供者方法。

在这种方法中,您在主包中定义服务提供者接口 (SPI),并使用 java META-INF/services 位置来查找实现。在这种情况下,您只需将 jar 文件放在类路径中即可添加扩展。

从 java 1.6 开始,您可以使用 java.util.ServiceLoader。

或者你看看 apache 发现 http://commons.apache.org/proper/commons-discovery/apidocs/org/apache/commons/discovery/tools/Service.html

它比 java.util.SerivceLoader 更强大,因为它允许您将构造函数参数传递给它实例化的服务。

一个可能的插件加载器实现可能如下所示:

public interface ServiceInterface {

}

public class PluginHost {   

    public ServiceLoader<ServiceInterface> loadPlugins() {
        File[] pluginLibraries = getPluginLibraries();
        URL[] pluginLibUrls = new URL[pluginLibraries.length];

        for (int i = 0; i < pluginLibUrls.length; i++) {
            try {
                pluginLibUrls[i] = pluginLibraries[i].toURI().toURL();
            } catch (MalformedURLException e) {
                throw new IllegalStateException("Unable to load plugin: "
                        + pluginLibraries[i], e);
            }
        }

        URLClassLoader pluginsClassLoader = new URLClassLoader(pluginLibUrls,
                ServiceInterface.class.getClassLoader());

        ServiceLoader<ServiceInterface> serviceLoader = ServiceLoader.load(
                ServiceInterface.class, pluginsClassLoader);

        return serviceLoader;
    }

    private File[] getPluginLibraries() {
        // please implement
    }
}
于 2013-07-05T09:18:48.920 回答
1

这是可能的。

罐子只是压缩的类文件。

只要类文件在类路径中就可以了。


解压缩 jar 文件(从 .jar 重命名为 .zip 并解压缩)以查看 java 包的目录结构应该是什么。

于 2013-07-05T09:17:18.730 回答
0

有关简单的扩展机制,请查看ServiceLoader

有关更完整的扩展机制,请查看 OSGi。

于 2013-07-05T09:20:29.777 回答
0

当然,您可以在运行时加载一个类并创建一个 Class 对象:

看到这个Class#forName(String, boolean, ClassLoader) API

有关示例,请参阅本教程。

于 2013-07-05T09:17:42.323 回答