ExpandoMetaClass в Grails для переопределения поведения в библиотеке Java?
Я использую Grails со сторонними библиотеками Java, и я хотел бы переопределить поведение в одной из этих библиотек.
Я попытался сделать это в Bootstrap.groovy, вот так:
// class overrides
ExpandoMetaClass.enableGlobally()
SimpleStringFilter.metaClass.passesFilter = {Object itemId, Item item ->
final Property<?> p = item.getItemProperty(propertyId);
if (p == null) {
return false;
}
Object propertyValue = p.getValue();
if (propertyValue == null) {
return false;
}
final String value = ignoreCase ? propertyValue.toString()
.toLowerCase() : propertyValue.toString();
if (onlyMatchPrefix) {
if (!value.startsWith(filterString)) {
return false;
}
} else {
if (!value.contains(filterString)) {
return false;
}
}
return true;
}
Я точно знаю, что метод passFilter в классе SimpleStringFilter вызывается, но я установил точку останова в моем коде выше, и он никогда не срабатывает.
Для справки, подпись метода Java:
public boolean passesFilter(Object itemId, Item item)
Итак, можно ли вообще переопределить поведение в библиотеках Java с ExpandoMetaClass глобально? Может кто-нибудь объяснить поведение и нюансы его использования таким образом?
Спасибо!
1 ответ
Проблема, с которой вы сталкиваетесь, заключается в том, что классы Java не вызывают metaClass
, Groovy не может переопределить вызовы методов для классов Java, используя metaClass
,
Это распространенное недоразумение, когда вы видите что-то вроде этого:
def object = new MyJavaObject()
object.metaClass.someMethod = { ... }
То, что на самом деле происходит выше, это то, что вы создаете объект Groovy, который оборачивает MyJavaObject
который затем позволяет этому экземпляру вызываться через метакласс.