在scala中动态创建类,我应该使用解释器吗?

时间:2010-05-02 01:55:31

标签: scala runtime interpreter javabeans

我想在 Scala 中的运行时创建一个类。现在,只考虑一个简单的例子,我想用一些属性来构造一个 java bean,我只在运行时知道这些属性。

如何创建scala类?我愿意从scala源文件创建,如果有一种方法来编译它并在运行时加载它,我可能想要因为我有时有一些复杂的功能,我想添加到类。 我该怎么做?

我担心我读到的scala解释器是对它加载的解释代码进行沙盒化,以便托管解释器的一般应用程序无法使用它?如果是这种情况,那么我将无法使用动态加载的scala类。

无论如何,问题是,如何在运行时动态创建一个scala类并在我的应用程序中使用它,最好的情况是在运行时从scala源文件加载它,如interpreterSource("file.scala")和它加载到我当前的运行时,第二个最好的情况是通过调用方法 createClass(...)来创建它在运行时创建它。

谢谢,菲尔

1 个答案:

答案 0 :(得分:7)

没有足够的信息来了解最佳答案,但请记住您在JVM上运行,因此任何适用于Java的技术或字节码工程库在此都应该有效。

您可能会使用数百种技术,但最佳选择完全取决于您的确切用例,因为许多技术不是通用的。这里有几个想法:

  • 对于一个简单的bean,你也可以 只需使用地图,或查看 来自apache commons的DynaBean课程。

  • 您可以获得更高级的行为 显式调用编译器 然后获取生成的.class文件 通过类加载器(这主要是 JSP如何做到这一点)

  • 解析器和自定义DSL非常适合 一些案例。和豆壳一样 脚本。

点击此处查看ScalaDays视频:http://days2010.scala-lang.org/node/138/146 它演示了如何使用Scala作为符合JSR-223的脚本语言。 这应该涵盖您希望在运行时评估Scala的大多数场景。

您还需要查看此处的电子邮件主题:http://scala-programming-language.1934581.n4.nabble.com/Compiler-API-td1992165.html#a1992165

这包含以下示例代码:

// We currently call the compiler directly 
// To reduce coupling, we could instead use ant and the scalac ant task 

import scala.tools.nsc.{Global, Settings} 
import scala.tools.nsc.reporters.ConsoleReporter
{ 
  // called in the event of a compilation error 
  def error(message: String): Nothing = ... 

  val settings = new Settings(error) 
  settings.outdir.value = classesDir.getPath 
  settings.deprecation.value = true // enable detailed deprecation warnings 
  settings.unchecked.value = true // enable detailed unchecked warnings 

  val reporter = new ConsoleReporter(settings) 

  val compiler = new Global(settings, reporter) 
  (new compiler.Run).compile(filenames) 

  reporter.printSummary 
  if (reporter.hasErrors || reporter.WARNING.count > 0) 
  { 
             ... 
  } 
} 


val mainMethod: Method = { 
  val urls = Array[URL]( classesDir.toURL ) 

  val loader = new URLClassLoader(urls) 

  try { 
    val clazz: Class = loader.loadClass(...) 

    val method: Method = clazz.getMethod("main", Array[Class]( classOf[Array[String]] )) 
    if (Modifier.isStatic(method.getModifiers)) { 
       method 
    } else { 
      ... 
    } 
  } catch { 
    case cnf: ClassNotFoundException => ... 
    case nsm: NoSuchMethodException => ... 
  } 
} 

mainMethod.invoke(null, Array[Object]( args ))