我IntegerMetaClass
只想在给定的GroovyShell
上下文中使用自定义。
原因是不要用我潜在的“令人不安”来污染整个运行时IntegerMetaClass
。
当我将 IntegerMetaClass.java 实现放入魔术包时,它就像一个魅力groovy.runtime.metaclass.java.lang
。但是,当我尝试手动将其添加到中间 GroovyClassLoader 时,它停止工作。
// Pseudo-code without try catch, etc
// Within my eval factory
GroovyClassLoader gcl = new GroovyClassLoader(getClass().getClassLoader());
URL url = getClass().getClassLoader().getResource("groovy/runtime/metaclass/java/lang/IntegerMetaClass.groovy"); // I rename it to .groovy file
GroovyCodeSource gcs = new GroovyCodeSource(url);
Class<?> clazz = gcl.parseClass(gcs);
// clazz is not null here and equals to what I expect:
// Class<groovy.runtime.metaclass.java.lang.IntegerMetaClass>
// Now trying to use it in a groovy shell
GroovyShell gs = new GroovyShell(gcl);
gs.evaluate("10.minutes"); // Where .minutes is part of my IntegerMetaClass
// Fail with an NoSuchProperty exception
GroovyClassLoader
除了“解析” MetaClass 之外,我是否还有其他事情要做?其他地方?
更新1:
如上所述,IntegerMetaClass.minutes
当我将它直接放在我的 java 源类路径中时,查找正在工作。
package groovy.runtime.metaclass.java.lang;
import groovy.lang.DelegatingMetaClass;
import groovy.lang.MetaClass;
public class IntegerMetaClass extends DelegatingMetaClass {
public IntegerMetaClass(Class<Integer> delegate) {
super(delegate);
}
public IntegerMetaClass(MetaClass delegate) {
super(delegate);
}
@Override
public Object getProperty(Object object, String property) {
if ("minutes".equals(property)) {
Integer q = (Integer) object;
return new Minutes(q);
}
return super.getProperty(object, property);
}
}
更新2:
一个可能但不令人满意的解决方案:
gcl.parseClass
在通话后添加以下内容
Constructor<?> constructor = clazz.getConstructor(Class.class);
DelegatingMetaClass dmc = (DelegatingMetaClass) constructor.newInstance(Integer.class);
dmc.initialize();
InvokerHelper.getMetaRegistry().setMetaClass(Integer.class, dmc);
但是这个解决方案必须在 MetaClass 源和原始目标类之间保持一种“映射”,以支持超过Integer
......