0

Groovy スクリプトで定義されたクラスのメソッドを別の Groovy スクリプトから動的に変更および追加しようとしましたが、クラス名を .metaClass で直接使用するとなぜ機能するのかわかりません。ただし、GroovyClassLoader を使用してクラスをロードする場合はそうではありません (これを行う必要があります!)。

1つのファイル「MyTest.groovy」に

class MyTest {

   public void setUp() {
      println "SET UP"
   }
   public void tearDown() {
      println "TEAR DOWN"
   }
   public void testA() {
      println "testA"
   }
}

および別のファイル「suite.groovy」が含まれています

#!/usr/bin/env groovy

public class MyTestSuite {
   // For debug
   public static printClassLoader(Class cls) {
      ClassLoader loader = cls.classLoader
      while (loader) {
         println loader.class
         println loader.URLs.join("\n")
         println "\n\n"
         loader = loader.parent
      }
   }

   public static void suite()  {
      // First method to define my class (change/addition of methods works)
      //Class testClass = MyTest

      // Second way to define my class (change/addition of methods doesn't work)
      ClassLoader parent = MyTestSuite.class.getClassLoader();
      GroovyClassLoader gcl = new GroovyClassLoader(parent);
      Class testClass = gcl.parseClass(new File("MyTest.groovy"));

      printClassLoader(testClass)

      testClass.metaClass.setUp = {-> println "I'm your new setUp()" ;}
      testClass.metaClass.newTest = {-> println "I'm your new newTest()" ; }
   }
}

MyTestSuite.suite()
MyTest aTest = new MyTest()
aTest.setUp()
aTest.newTest()

最初の方法では、期待される結果が得られます。

I'm your new setUp()
I'm your new newTest()

しかし、私が得る2番目のもので

SET UP
Caught: groovy.lang.MissingMethodException: No signature of method: MyTest.newTest() is applicable for argument types: () values: []
Possible solutions: testA(), getAt(java.lang.String), wait(), inspect(), every()
    at suite.run(suite.groovy:34)

興味深いことに、既存のメソッドを変更しても機能しませんが、例外はありませんが、新しいメソッドを追加しようとするとスローされます。使用されているクラスローダーで何かをしなければならないと思いますが、何を正確に何を変更すればよいのかわかりません! 最初のバージョンでは、次のクラス ローダーが呼び出されます。

class groovy.lang.GroovyClassLoader$InnerLoader
class groovy.lang.GroovyClassLoader
class org.codehaus.groovy.tools.RootLoader
class sun.misc.Launcher$AppClassLoader
class sun.misc.Launcher$ExtClassLoader

2 番目のバージョンの場合:

class groovy.lang.GroovyClassLoader$InnerLoader
class groovy.lang.GroovyClassLoader
class groovy.lang.GroovyClassLoader$InnerLoader
class groovy.lang.GroovyClassLoader
class org.codehaus.groovy.tools.RootLoader
class sun.misc.Launcher$AppClassLoader
class sun.misc.Launcher$ExtClassLoader

どんなアイデアでも大歓迎!
フランク

4

1 に答える 1

0

new GroovyClassLoader現在のスレッドの Groovy クラスローダではありません。メソッドが終了すると、それ自体および関連付けとともに破棄
されます。suite()ClassMetaClass

ただし、これは機能します。

Class testClass = gcl.parseClass(new File("MyTest.groovy"));
testClass = Class.forName(testClass.getName())
于 2010-11-27T15:40:03.350 に答える