java - 动态添加 IntegerMetaClass 到 GroovyShell

标签 java groovy metaclass groovyshell groovyclassloader

我只想在给定的 GroovyShell 上下文中使用自定义 IntegerMetaClass

原因是为了不让我的潜在“干扰”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 ...

最佳答案

您可以使用 GroovyShell 类加载器加载类:

    GroovyShell gs = new GroovyShell()
    gs.loader.loadClass('groovy.runtime.metaclass.java.lang.IntegerMetaClass')
    gs.evaluate("10.minutes")

注意:当 IntegerMetaClass 是 groovy 文件时,我得到了 java.lang.IncompatibleClassChangeError,但当它是 java 时没有问题。这可能与我的环境设置有关

关于java - 动态添加 IntegerMetaClass 到 GroovyShell,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26526234/

相关文章:

java - 在 Java 中使用迭代器的多个 If 条件

groovy - 如何使用 groovy mixin 添加静态方法

java - Gradle获取其他项目的jar文件路径

python - 元类的继承

python 3.2 插件工厂 : instantiation from class/metaclass

java - 构建文件中“找不到主类错误”

java - 我正在将图像上传到 Firebase Storage,然后需要将图像 URL 作为文本添加到 Firebase 数据库中

java - Kafka Connect + Zookepeer 未连接

grails - 在 Grails 中使用 Groovy++ 的经验

python - 创建一流的对象,它的所有实例属性都是只读的,就像切片一样?