1

私の目標は、関数が事前定義され、インターセプターが実行時間とクロージャー評価の結果をログアウトするバインディングを使用して groovy スクリプトを実行することです。私のサンプルコードは次のとおりです。

  binding.login = { ->
     binding.event.appname=='login'
  }  def gse = new GroovyScriptEngine("src/main/resources/rules")
  gse.run('DSL.groovy', binding)

スクリプト内で login メソッドを呼び出しています。MetaClass を使用してインターセプトする方法を理解できないことを除いて、すべてが機能します。私の試みのような

  Binding.metaClass.invokeMethod = { String name, args ->
                       println ("Call to $name intercepted... ")

動作しませんでした。後で、クロージャーはバインディングのプロパティであり、メソッドではないことがわかりました。このシナリオでインターセプトを実行する方法とその方法はありますか? メタクラスの正しいオブジェクトは何ですか? 注記のとおり、私のクロージャーは別のネストされたクロージャー内で実行されました。ありがとう

4

1 に答える 1

0

それがより良い解決策かどうかはわかりませんが、バインディングのクロージャーを装飾することで、あなたが望むことを何とかすることができました

binding = new Binding([
    login : { -> println "binding.login called" },
    echo : { String text -> println "test for $text" },
    foo : { a, b, c -> println "$a $b $c" }
])


binding.variables.each { key, value ->
    if (value instanceof Closure) 
    {
        binding.variables[key] = { Object[] args -> 
            long t0 = System.currentTimeMillis()

            value( *args )

            print "[$key method"
            print " args: $args "
            println " time: ${System.currentTimeMillis() - t0}]"
        }
    }
}


def gse = new GroovyScriptEngine(".")

gse.run('Bind.groovy', binding)

そして、これは私のものBind.groovyです:

println " ** executing bind"
login()
echo("echo")
foo("test", 4, "echo")
println " ** bind script done"

MissingMethodExceptionメソッドをバインディングでクロージャとして定義していない場合は、 a を try/catch することもできます。

また、DSL の作成については、Laforge のスライド共有をお勧めします。

http://www.slideshare.net/glaforge/going-to-mars-with-groovy-domainspecific-languages

このスライドシェアでは、スクリプトを拡張するクラスを使用したバインドを Laforge が示しています。それは良いアプローチだと思います。さらに○○。

アップデート

メソッド呼び出しをベース Script クラスに委任するという mrhaki の提案を見てください (Guillaume のスライドシェアにもあります)。

http://mrhaki.blogspot.com.br/2011/11/groovy-goodness-create-our-own-script.html

JFugue で DSL を実装するためにそれを使用したところ、すぐに機能しました。

于 2012-08-31T21:23:03.343 に答える