Невозможно динамически изменять или добавлять методы в классе, используя GroovyClassLoader

Я пытаюсь динамически изменять и добавлять методы класса, определенного в скрипте groovy, из другого скрипта groovy, но не могу понять, почему он работает, если я использую имя класса непосредственно в.metaClass. но не, если я загружаю класс, используя GroovyClassLoader(что мне нужно сделать!).

В одном файле '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()

Но со вторым я получаю

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

Для второй версии:

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

Любая идея приветствуется!
Franck

1 ответ

new GroovyClassLoader не является загрузчиком классов Groovy текущего потока.
Он будет утилизирован после suite() Метод заканчивается - вместе со своим Class а также MetaClass ассоциации.

Тем не менее, это работает:

Class testClass = gcl.parseClass(new File("MyTest.groovy"));
testClass = Class.forName(testClass.getName())
Другие вопросы по тегам