似乎需要某种插件架构,而不是使用 DLL 本身。
除非必要,否则我不建议使用 DLL 的一个原因是,将 Java 代码与本机代码链接将需要使用 Java Native Interface (JNI),这可能比纯 Java 解决方案需要更多的努力。
一种相对简单的方法是使用 Java 的 reflection 功能。
根据所提供的信息,我可能会遵循以下思路:
- 为输出格式定义一个接口。
- 创建一个实现接口的 Java 类。
- 从classpath 获取课程。
- 使用反射动态加载类。 (使用
Class.newInstance方法可以从ClassLoader加载的class文件中实例化对象。)
通过这些步骤,可以实现一个简单的插件,在需要支持新格式时不需要完全重建。
第 1 步:定义接口
假设我们最终得到如下界面:
public interface Outputter {
public void write(Data d);
}
第 2 步:制作实现类
然后,我们将创建一个实现类。
public class TextOutputter {
public void write(Data d) {
// ... output data to text
}
}
然后,编译上述内容,我们将得到一个名为 TextOutputter.class 的 class 文件。
第 3 步:使类从类路径可用
在运行主应用程序时,我们需要在classpath 中包含上述TextOutputter.class。通常,我们会告诉 JVM 一个位置列表来考虑作为类路径,其中应该包括上面的 class 文件。
完成后,我们应该能够使用反射加载上述类。
第 4 步:使用反射动态加载类
现在,当我们真正想要加载上述类时,我们会执行以下操作:
// Note: We load the class by specifying the fully-qualified class name!
Class<?> clazz = Class.forName("TextOutputter");
// Then, we instantiate the class.
// Note that the following method will call the no-argument constructor.
Outputter outputter = clazz.newInstance();
// Now, we can give data to the TextOutputter object that we loaded dynamically.
outputter.write(...);
Class.forName 方法用于尝试从默认的ClassLoader 中查找TextOutputter 类。一旦我们将类作为Class 表示形式获得,我们就可以实例化该类的一个对象。
可以使用Class.newInstance 方法来实例化对象。如果应该使用无参数构造函数以外的其他东西,则必须获取该类的 Constructor,然后从那里实例化对象。
然后将通过反射实例化的对象放入Outputter 变量中,因此可以在TextOutputter 上调用write 方法。
添加更多格式需要上述过程,但只需更改全限定类名称(例如,String,FQCN 为 java.lang.String)即可加载不同的类。
简而言之,这就是动态加载class 文件并在您的应用程序中使用它所需要的。
(顺便说一句,我并没有真正编译上面的代码,所以这里和那里可能会有一些错误,但我希望我能说明它所需要的过程。)