【问题标题】:loading JRuby classes from Java by Class.forName通过 Class.forName 从 Java 加载 JRuby 类
【发布时间】:2009-11-04 22:18:06
【问题描述】:

我在 Java 代码中有以下类:

public class CHRTreeCreator extends IndexCreator { ... }

而不是CHRTreeCreator,我想使用同样扩展IndexCreator 的不同实现,但我想在JRuby 中对其进行编码。问题是,IndexCreator的具体实现是根据xml配置文件选择的:

<creator>dwe.index.tree.chr.CHRTreeCreator</creator>

代码如下所示:

// className is fetched from XML
Class creatorClass = Class.forName(className);
Constructor constructor = creatorClass.getConstructor(new Class[] {  });
creator = (IndexCreator) constructor.newInstance(new Object[] { });

问题是,是否可以在 Ruby 中实现它,像这样:

class MyIndexCreator < IndexCreator
end

并以某种方式将 MyIndexCreator 类名放入 XML 配置文件中。在这种情况下,模块 - 包映射如何工作?

如果无法通过 Java 的 Class.forName 加载 Ruby 类,我应该如何解决这个问题?

【问题讨论】:

    标签: java jruby classloader


    【解决方案1】:

    目前 JRuby 子类无法通过 Java 以这种方式访问​​,尽管它计划在未来实现(可能是 JRuby 1.5)的某些容量。

    一个选项(取决于您的类的 API)是创建一个委托:

    public class RubyIndexCreator extends IndexCreator {
      private IndexCreator rubyCreator;
      public RubyIndexCreator() {
        ScriptEngineManager factory = new ScriptEngineManager();
        ScriptEngine engine = factory.getEngineByName("ruby");
        FileReader r = new FileReader("ruby_index_creator.rb");
        try {
          rubyCreator = engine.eval(r);
        }
        finally {
          r.close();
        }
      }
    
      public Object create(String someArg) {
        return rubyCreator.create(someArg);
      }
    }
    

    我已经掩盖了一些缓存的机会,也只是概述了管理文件阅读器,但希望你能明白。

    在这个特定的示例中,ruby_index_creator.rb 将实现您的索引创建器类,然后返回它的一个实例 - 显然,您可以从这里引用其他 ruby​​ 文件,并根据需要进行组织:

    class MyIndexer < IndexCreator
     [...]
    end
    MyIndexer.new
    

    就是这样!

    【讨论】:

      【解决方案2】:

      作为替代方案,也许您可​​以利用 Ruby 的开放类并直接修改 CHRTreeCreator 的行为(而不是子类化)。

      【讨论】:

      • 感谢 Rob,该解决方案在我的情况下可以以某种方式工作(我现在确实这样做了),但我不希望对 Java 类进行猴子补丁。应该有一些通用的方法来使用 .forName 方法加载 Ruby 类,对吧?
      【解决方案3】:

      使用 ruby​​ eval 怎么样:

      C:\>jirb
      irb(main):001:0> require 'java'
      => false
      irb(main):002:0> class MyDate < Java::JavaUtil::Date
      irb(main):003:1> def my_method;puts "hi there";end
      irb(main):004:1> end
      => nil
      irb(main):005:0>
      irb(main):006:0* c = "MyDate"
      => "MyDate"
      irb(main):007:0> obj = eval("#{c}.new")
      => #<MyDate:0xd2efa1>
      irb(main):008:0> obj.my_method
      hi there
      => nil
      irb(main):009:0>
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多