我目前正在开发一个Java项目,我有一组数据,我希望以多种自定义格式输出。我为每种格式都有一个类,它接收原始数据并相应地转换它。但是,首先,我只实现了这些格式中的两种或三种,但希望允许在以后添加更多格式,而无需对应用程序进行大规模重建。
我的想法是为每个格式类创建一个DLL,让我的应用程序传递要转换为每个格式的数据。这样,我可以稍后创建一个DLL并让我的主应用程序访问它。 (我很乐意听取任何替代方法,因为有人在C ++ / C#中做过这个,之后感觉就像逻辑解决方案,但它可能不适用于Java)
我的问题是我完全不知道如何做到这一点 - 在C ++ / C#中我可以用几行代码编写它,但我不确定它如何与Java一起工作。有可能提出一个非常模糊的问题,我该怎么办呢?
非常感谢答案,并提供饼干和茶。 :)
提前致谢, 中号
编辑:对不起,只是为了补充:我也不确定如何创建DLL,这个项目必须是Java,必须首先阅读。谢谢。 :)
答案 0 :(得分:5)
而不是使用DLL本身,似乎需要的是某种插件架构。
除非有必要,否则我不建议使用DLL的一个原因是将Java代码与本机代码链接将需要使用Java Native Interface(JNI),这可能需要比纯Java解决方案更多的努力。
一种相对简单的方法是使用Java的reflection功能。
根据所提供的信息,我可能会按照以下方式进行:
Class.newInstance
方法可以实例化class
加载的ClassLoader
文件中的对象。)通过这些步骤,可以实现一个简单的插件,当需要支持新格式时,不需要完全重建。
第1步:定义界面
假设我们最终得到如下界面:
public interface Outputter {
public void write(Data d);
}
第2步:制作实施课程
然后,我们将创建一个实现类。
public class TextOutputter {
public void write(Data d) {
// ... output data to text
}
}
然后,在编译上述内容时,我们最终会得到一个名为class
的{{1}}文件。
第3步:从类路径中提供课程
运行主应用程序时,我们需要在classpath中使用上述TextOutputter.class
。通常情况下,可以告诉JVM一个要考虑作为类路径的位置列表,并且应该包含上面的TextOutputter.class
文件。
完成后,我们应该能够使用反射加载上述类。
第4步:使用反射动态加载课程
现在,当我们真正想加载上面的类时,我们会做类似以下的事情:
class
Class.forName
方法用于尝试从默认// 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(...);
中查找TextOutputter
类。一旦我们将类作为Class
表示获取,我们就可以实例化该类的对象。
可以使用Class.newInstance
方法执行对象的实例化。如果应该使用除无参数构造函数之外的其他东西,则必须获取该类的ClassLoader
继续从那里实例化该对象。
然后通过反射实例化的对象放入Constructor
变量,因此可以在Outputter
上调用write
方法。
添加更多格式将需要上述过程,但是更改完全限定的类名(例如,对于TextOutputter
,FQCN是String
)是加载不同类所需的全部内容。
简而言之,这就是动态加载java.lang.String
文件并从您的应用程序中使用它所需要的。
(正如旁注,我实际上并没有编译上面的代码,因此可能存在一些错误,但我希望我可以说明它将采取的过程。)
答案 1 :(得分:2)
我做过这样的事情。 我创建了一个基于Java的开放式插件体系结构POJO,甚至可以重新加载更新的插件类。 JNI是处理本机代码的接口。 唯一的技术部分是重写一个在运行时动态地重新加载DLL的类加载器。 但是,如果您只进行“离线”更新,则不需要这样的事情。
答案 2 :(得分:1)
如果要在java中使用编写本机代码(编译为DLL),您需要查看Java Native Interface (JNI)。
更新您可以使用System.loadLibrary(String libName)
(如果您知道库名称和库路径已设置)或System.load(String filename)
(库文件名)来加载库(DLL)的java。
答案 3 :(得分:1)
您可以随时使用System.loadLibrary()加载新的DLL。但是,您可能需要加载一个java类来绑定它。
您可能会发现使用OSGi容器很有用,因为它支持加载和卸载模块(包括共享库)
我建议使用karaf和iPOJO,但还有很多其他的。
答案 4 :(得分:1)
我认为你可以忽略JNI路径。我的印象是你使用dll一词是因为缺少一个更好的词,你真的不需要一个dll。
您可以在Java中执行相同的操作,但是您将过滤器放在jar文件而不是dll中。
基本上就是这样。
答案 5 :(得分:1)
Java SE 6引入了ServiceLoader类: http://download.oracle.com/javase/6/docs/api/java/util/ServiceLoader.html
如果您需要适当的模块化方法,请考虑NetBeans平台(特别是如果它是桌面应用程序)或OSGi。