这发生在编译本身中。让我们看一个更简单的例子。
class Main {
static void main(def args) {
Foo foo = new Foo()
foo.str = ""
foo.str
}
}
对于 Groovy 类
class Foo {
String str
}
如果你反编译Main
类,你会看到它是
public class Main implements GroovyObject {
public Main() {
Main this;
CallSite[] arrayOfCallSite = $getCallSiteArray();
MetaClass localMetaClass = $getStaticMetaClass();
this.metaClass = localMetaClass;
}
public static void main(String... args) {
CallSite[] arrayOfCallSite = $getCallSiteArray();
Foo foo = (Foo)ScriptBytecodeAdapter.castToType(arrayOfCallSite[0].callConstructor(Foo.class), Foo.class);
String str = "";
ScriptBytecodeAdapter.setGroovyObjectProperty(str, Main.class, foo, (String)"str");
arrayOfCallSite[1].callGroovyObjectGetProperty(foo);
}
}
A .[property] =
调用被编译为ScriptBytecodeAdapter.setGroovyObjectProperty
,进而调用链MetaClassImpl.setProperty
> MetaMethod.doMethodInvoke
> CachedMethod.invoke
> java.lang.reflect.Method.invoke
> [setter]
And a .[property]
调用被编译为arrayOfCallSite[1].callGroovyObjectGetProperty
,进而调用链AbstractCallSite.callGroovyObjectGetProperty
> GetEffectivePogoPropertySite.getProperty
> MethodMetaProperty$GetBeanMethodMetaProperty.getProperty
> MetaMethod.doMethodInvoke
> CachedMethod.invoke
> java.lang.reflect.Method.invoke
> [getter]
对于 Java 类
如果您使用被调用类的 Java 版本,如下所示
public class Foo {
private String str;
public String getStr() {
return str;
}
public void setStr(String str) {
this.str = str;
}
}
相同Main
反编译为
public class Main implements GroovyObject {
public Main() {
Main this;
CallSite[] arrayOfCallSite = $getCallSiteArray();
MetaClass localMetaClass = $getStaticMetaClass();
this.metaClass = localMetaClass;
}
public static void main(String... args) {
CallSite[] arrayOfCallSite = $getCallSiteArray();
Foo foo = (Foo)ScriptBytecodeAdapter.castToType(arrayOfCallSite[0].callConstructor(Foo.class), Foo.class);
String str = "";
ScriptBytecodeAdapter.setProperty(str, null, foo, (String)"str");
arrayOfCallSite[1].callGetProperty(foo);
}
}
A .[property] =
调用被编译为ScriptBytecodeAdapter.setProperty
,进而调用链[Class].setProperty
> InvokerHelper.setProperty
-> MetaClassImpl.setProperty
> MetaMethod.doMethodInvoke
> CachedMethod.invoke
> java.lang.reflect.Method.invoke
> [setter]
And a .[property]
调用被编译为arrayOfCallSite[1].callGroovyObjectGetProperty
,进而调用链AbstractCallSite.callGetProperty
> GetEffectivePojoPropertySite.getProperty
> MethodMetaProperty$GetBeanMethodMetaProperty.getProperty
> MetaMethod.doMethodInvoke
> CachedMethod.invoke
> java.lang.reflect.Method.invoke
> [getter]
更正您的代码
正如您从这些调度链中看到的,您已经正确地覆盖了 getter(因为它发生在类本身中),但是如果您想覆盖getProperty
or setProperty
,你必须在metaClass
,而不是类本身。您所看到的行为是预期的。此代码演示了如何重写每个
class Foo {
String bar
}
// override using setter in category
@Category(Foo)
class FooCategory {
public String getBar() {
println "in getter"
}
public void setBar(String bar) {
println "in setter"
}
}
use (FooCategory) {
Foo foo = new Foo()
foo.bar = ""
foo.bar
}
// override using metaClass
Foo.metaClass.getProperty { String pname ->
println "in getProperty"
}
Foo.metaClass.setProperty { String pname, Object pValue ->
println "in setProperty"
}
Foo foo = new Foo()
foo.bar = ""
foo.bar
outputs
in setter
in getter
in setProperty
in getProperty
并且因为getProperty
/setProperty
call 使调度(最终)到 getter/setter,您可以完全阻止 getter/setter 被调用,如下所示
class Foo {
String bar
}
Foo.metaClass.getProperty { String pname ->
println "in getProperty"
}
Foo.metaClass.setProperty { String pname, Object pValue ->
println "in setProperty"
}
@Category(Foo)
class FooCategory {
String getBar() {
println "in getter"
}
void setBar(String bar) {
println "in setter"
}
}
use (FooCategory) {
Foo foo = new Foo()
foo.bar = "hi foo1"
foo.bar
}
outputs
in setProperty
in getProperty