我正在研究一个使用Groovy作为编译时依赖项的
Java模块,我想在不编写Groovy代码的情况下向我的Java类Person(如
Groovy JDK)添加一个方法.
在Groovy中,我会像那样实现它
Person.meta.doSomething = { String param -> println "do something: ${param}" }
如何使用Groovy API表单Java来完成它?
编辑1:
到目前为止我已经实现了以下内容,我几乎就在那里.我为Person实例化一个Expando类,并注册一个MethodClosure,它将方法调用委托给PersonDefaultMethods类中的方法.
ExpandoMetaClass expando = new ExpandoMetaClass (Person.class, true, false);
expando.registerInstanceMethod ("format", new MethodClosure (new PersonDefaultMethods(), "format"));
expando.initialize ();
PersonDefaultMethods包含我在Expando类中声明的方法的实现.
public class PersonDefaultMethods {
public String format(String format) {
return this.toString(); // this one gets called
}
public String format(Person self, String format) { // but I want this method to be called
return self.getFirstname() + " " + self.getLastname();
}
}
当我知道在这个上下文中执行Groovy脚本时,我能够在Person实例上调用format方法,但是我无法像通常使用闭包那样访问委托.
编辑2:
在我的实现中,使用闭包子类或匿名闭包类的方法失败了.
ExpandoMetaClass expando = new ExpandoMetaClass(Person.class, true, false);
expando.registerInstanceMethod("format", new Closure(this) {
@Override
public Object call(Object arguments) {
return super.call(arguments);
}
@Override
public Class[] getParameterTypes () {
return new Class[] { String.class};
}
});
expando.initialize ();
这样做了.谢谢.
最佳答案 您可以通过GroovySystem.getMetaClassRegistry()获取当前的元类.getMetaClass(Person.class);更好.但要模拟上述内容,您需要手动完成Groovy在后台为您做的几件事.
>首先,您需要一个ExpandoMetaClass(短EMC).如果上面的元类不是EMC,则需要创建一个并在注册表中注册它:ExpandoMetaClass emc = new ExpandoMetaClass(Person.class).
>接下来,您需要使用String和Closure或MetaMethod调用registerInstanceMethod.上面的变体是Closure版本,将在后台调用另一个版本.
>要遵循Groovy约定,您需要使用Signature的doCall方法创建一个Closure子类(可能是匿名的). registerInstanceMethod的字符串将是方法的名称
>您当然也可以利用其中一个现有的MetaMethod子类(或您自己的子类)来实现目标.