Использование invokeMethod
перехватывает все вызовы методов и свойств согласно Использование invokeMethod и getProperty .Если вы хотите, чтобы он прошел до message()
, вы должны добавить условие if, чтобы проверить, является ли имя метода «message», или изменить invokeMethod
на methodMissing
.
РЕДАКТИРОВАТЬ:
Поскольку вы пытаетесь перехватить вызов, я думаю, что проблема может заключаться в том, что переадресация invoke
не получает правильный мета-метод.То есть, поскольку вы используете metaClass
из this
, вы получите MixinInstanceMetaMethod
, потому что this.metaClass
относится к MixedInMetaClass
.Учитывая, что у вас есть MetaMethod
, его следует вызывать у владельца метакласса (который должен быть Bar
).
Следующий код должен работать:
import org.junit.Test
import static org.junit.Assert.*
class MixinPropertyTest {
static class Foo {
def message
def invokeMethod(String name, args) {
System.out.println "invokeMethod sees ${message}"
System.out.println "invoking ${name}"
def metaMethod = this.metaClass.getMetaMethod(name, args)
metaMethod?.invoke(this.metaClass.owner, args)
}
String message() {
message
}
}
@Mixin(Foo)
static class Bar {
}
@Test
void test() {
assertEquals 'hello', new Bar(message: 'hello').message()
}
}
Дальнейшее уточнение:Я думаю, потому что this
, который вы передаете в metaMethod.invoke, уже является экземпляром mixin, причина, по которой this
изменяется, заключается в том, что metaMethod - это MixinInstanceMetaMethod
, который пытается найти экземпляр mixin.Если он не найден, он создает новый экземпляр mixin, поэтому ссылка на this
отличается от invokeMethod
на message
метод.
Эта строка в исходном коде Groovy показывает, что вызов invoke
ищет экземпляр миксина.
Эта строка в источнике показывает создание нового экземпляра миксина:https://github.com/groovy/groovy-core/blob/master/src/main/org/codehaus/groovy/reflection/MixinInMetaClass.java#L68