【问题标题】:Groovy: writing dynamically compiled class to discGroovy:将动态编译的类写入磁盘
【发布时间】:2019-09-09 22:26:36
【问题描述】:

在我的应用程序中,我需要在运行时编译类/脚本。

作为Class:

Class<? extends LoginAdapter> clazz = groovyClassLoader.loadClass name
LoginAdapter la = clazz.newInstance id, logo

Closure:

Closure action = groovyShell.evaluate( script, name ) as Closure

这两种方式都很有魅力。

现在我需要能够将编译后的类/脚本写入一些持久性存储(光盘),然后在不从头开始编译的情况下恢复它们。

如何做到这一点?

【问题讨论】:

  • Serializable 应该会有所帮助。但是,从您的示例中不清楚您要存储什么:类或实例。你想如何重用存储的对象?
  • @daggett 我想存储课程。第二个例子也可以重新排列成一个类。
  • 理论上您可以扩展 GroovyClassLoader 并覆盖 createCollector ,后者用于从一个来源收集内存中编译的类。此方法中还有 CompilationUnit 可用,它实际上是进行编译,并具有 getClasses() 方法,该方法返回具有 getBytes() 方法的 GroovyClass 列表……但对我而言,使用 groovyc 运行编译更容易。
  • @daggett 感谢您的提示! groovyc 可以以编程方式运行吗?
  • groovyc 开始 org.codehaus.groovy.tools.FileSystemCompiler。检查一下。

标签: groovy classloader dynamic-class-loaders


【解决方案1】:

对于那些可能感兴趣的人,这是我的编程 kata:

class Base {
  String answer() { null }
  String question() { 'WHAT IS.... ?' }
}
class ClazzSpec extends Specification {

  def "test compile"() {
    given:
    String packageName = 'some.pckg'
    String body = """
package $packageName

class SomeClass extends Base {
  Closure cl = { a -> println a }
  @Override String answer(){ '42' }
  String json( m ){ JsonOutput.toJson( m ) }
  String longOne( int times ){ 
    times.times{ sleep 100 }
    'done'
  }
}
"""

    CompilerConfiguration cc = new CompilerConfiguration( targetDirectory:new File( './out' ) )
    ImportCustomizer imp = new ImportCustomizer()
    imp.addStarImports 'groovy.json', Base.package.name
    cc.addCompilationCustomizers imp, new ASTTransformationCustomizer( value:1, TimedInterrupt )

    new Compiler( cc ).compile packageName + '.SomeClass', body

    File base = new File( './out' )

    GroovyClassLoader gcl = new GroovyClassLoader()
    gcl.addClasspath './out'
    Class clazz = gcl.loadClass 'some.pckg.SomeClass'

    when:
    def inst = clazz.newInstance()

    then:
    inst.question() == 'WHAT IS.... ?'
    inst.answer() == '42'
    inst.json( [ q:42 ] ) == '{"q":42}'
    inst.longOne( 2 ) == 'done'

    when:
    inst.longOne 11

    then:
    thrown TimeoutException
  }

}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-08-18
    • 2017-10-12
    • 2017-10-19
    • 2021-09-22
    • 1970-01-01
    • 2012-11-01
    相关资源
    最近更新 更多