我有一个大数据集。我正在创建一个允许用户提交java源文件的系统,然后将其应用于数据集。更具体地说,每个提交的java源文件必须包含一个具有特定名称的静态方法,比如toBeInvoked()。 toBeInvoked将把一行数据集作为数组参数。我想在数据集的每一行上调用每个提交的源文件的toBeInvoked方法。我还需要实现安全措施(所以toBeInvoked()不能做I / O,不能调用exit等)。
目前,我的实现是这样的:我有一个java源文件名列表。对于每个文件,我创建了一个我编码的自定义安全ClassLoader的实例,它编译源文件并返回编译的类。我使用反射来提取静态方法toBeInvoked()(例如method = c.getMethod(“toBeInvoked”,double [] .class))。然后,我遍历数据集的行,并在每一行上调用该方法。
我的方法至少有两个问题:
有没有更好的方法来完成我想要做的事情?
答案 0 :(得分:0)
假设您的#toBeInvoked()可以在接口中定义而不是静态(它应该是!),您只需加载该类并将其强制转换为接口:
Class<? extends YourInterface> c = Class.forName("name", true, classLoader).asSubclass(YourInterface.class);
YourInterface i = c.newInstance();
然后直接调用#toBeInvoked()。
另请查看java.util.ServiceLoader,如果您有多个源文件,这可能有助于找到要加载的正确类。
答案 1 :(得分:0)
就个人而言,我会使用一个界面。这将允许您拥有多个具有自己状态的实例(对多线程很有用),但更重要的是,您可以使用接口,首先定义必须实现哪些方法,还要调用方法。
反射很慢,但这只与其他选项相关,例如直接方法调用。如果您正在扫描大型数据集,那么您必须从主内存中提取数据的事实可能要贵得多。
答案 2 :(得分:0)
鉴于您自己设定的限制,没有明显更好的方法。
对于它的价值,使这个“痛苦地慢”的原因是将源文件编译为类文件并加载它们。这比使用反射来调用方法要快许多个数量级。
(使用通用接口而不是静态方法不会对速度产生可测量的差异,并且复杂性的降低相对较小。)
如果您真的想要简化并加快速度,请更改您的体系结构,以便将代码作为包含所有已编译类的JAR文件提供。
答案 3 :(得分:0)
我建议您按照以下步骤解决问题。
希望这有帮助。 (请注意,我使用了类似的机制来在开发的Workflow Engine工具中动态加载工作流步骤类。)