3

JavaのGroovyのメタプログラミング機能を使用して、Stringオブジェクトのインスタンスにプロパティを追加できるようにしたいと思います。

Groovyからこれを行うのは簡単です:

class GroovyClass {
    def getDynamicString() {
        def myString = "hello"
        myString.metaClass.dynamicProperty = "there"
        return myString
    }
}

これが私のSpockテストケースです:

def "should add dynamic property"() {
    GroovyClass groovyClass = new GroovyClass()

    when:
    def theString = groovyClass.getDynamicString()
    then:
    theString == "hello"
    theString.dynamicProperty == "there"
}

ただし、Javaから同じことを実行し、同じテストを実行したいと思います。私が理解しているように、GroovyはStringなどのJDKクラスに追加のプロパティとメソッド(getMetaClassなど)を追加しますが、これをいつどのように行うかは正確にはわかりません。次の解決策は機能することがわかりましたが、GroovyShellを初期化し、メタプログラミングコードを文字列として記述するのは面倒なようです。

public String getDynamicString()
{
    String myString = "hello";
    GroovyShell shell = new GroovyShell();
    shell.setVariable("myString", myString);
    shell.setVariable("theDynamicPropertyValue", "there");
    shell.evaluate("myString.metaClass.dynamicProperty = theDynamicPropertyValue");
    return myString;
}

shell.evaluateを使用せずに上記を実行する方法はありますか?つまり、JavaからGroovyライブラリメソッドを直接呼び出すことによってですか?

4

1 に答える 1

7

したがって、このGroovyスクリプトを考えると:

def a = 'A String'

Decorator.decorate( a, 'foo', 'bar' )

assert a       == 'A String'
assert a.class == String
assert a.foo   == 'bar'

次に、Javaデコレータクラスを次のように記述できます。

import org.codehaus.groovy.runtime.HandleMetaClass ;
import org.codehaus.groovy.runtime.InvokerHelper ;

public class Decorator {
  public static void decorate( Object o, String name, Object value ) {
    HandleMetaClass hmc = new HandleMetaClass( InvokerHelper.getMetaClass( o ), o ) ;
    hmc.setProperty( name, value ) ;
  }
}

そして、Javaクラスをコンパイルし、Groovyスクリプトを実行すると、すべてのアサートが合格するはずです。

于 2013-03-18T13:36:40.657 に答える