Java 拦截groovy中所有元类的所有方法调用

Java 拦截groovy中所有元类的所有方法调用,java,groovy,Java,Groovy,我试图截获Java环境中运行的Groovy脚本中的所有方法调用 特别是我想检查所有方法调用的返回类型,如果它是X,我想用Y替换它 我知道可以在元类上使用invokeMethod进行拦截,但我只能对我编译的脚本类进行拦截。如果脚本依次调用类a上的一个方法,那么它将创建一个新的元类[a],如果之前没有从注册表手动获取该元类并用元方法覆盖它,我将无法截取该元类 我曾尝试使用GroovySystem.getMetaClassRegistry()在创建元类时添加侦听器,并在其中添加元方法,但它似乎从未触发

我试图截获Java环境中运行的Groovy脚本中的所有方法调用

特别是我想检查所有方法调用的返回类型,如果它是
X
,我想用
Y
替换它

我知道可以在元类上使用
invokeMethod
进行拦截,但我只能对我编译的脚本类进行拦截。如果脚本依次调用类
a
上的一个方法,那么它将创建一个新的
元类[a]
,如果之前没有从注册表手动获取该元类并用元方法覆盖它,我将无法截取该元类

我曾尝试使用
GroovySystem.getMetaClassRegistry()
在创建元类时添加侦听器,并在其中添加元方法,但它似乎从未触发

我希望这是自动的,而不必事先向我应该转换的方法添加注释,或者知道我要转换哪些类的方法。所有返回
X
的方法都应该返回
Y

我可以全局拦截所有方法调用吗

我可以拦截元类创建吗


我可以添加自动AST转换吗?

结果表明这是可能的。您需要通过调用
GroovySystem.getMetaClassRegistry().setMetaClassCreationHandle
来替换MetaClassCreationHandle

由于基类
MetaClassCreationHandle
是包私有的,因此从
ExpandoMetaClassCreationHandle
进行扩展可能更容易。但是要考虑到,让所有类都基于
ExpandoMetaClass
这一最常见的需求可能会有点过头。所以我做的是这样的:

GroovySystem.getMetaClassRegistry().setMetaClassCreationHandle(new ExpandoMetaClassCreationHandle() {

    @Override
    protected MetaClass createNormalMetaClass(Class theClass, MetaClassRegistry registry) {

        final List<Method> propertyMethods = new ArrayList<>();
        for (Method method : theClass.getDeclaredMethods()) {
            if (method.getReturnType() == TheMethodReturnTypeYouCareAbout.class) {
                propertyMethods.add(method);
            }
        }

        final MetaClass mc;
        if (propertyMethods.isEmpty() == false) {

            final ExpandoMetaClass expando = new ExpandoMetaClass(theClass, true, true);
            for (Method mm : propertyMethods) {
                final ClassInfo ci = ClassInfo.getClassInfo(mm.getDeclaringClass());
                expando.addMetaMethod(new MetaMethod() {

                    @Override
                    public int getModifiers() {
                        return mm.getModifiers();
                    }

                    @Override
                    public String getName() {
                        return mm.getName();
                    }

                    @Override
                    public Class getReturnType() {
                        return mm.getReturnType();
                    }

                    @Override
                    public CachedClass getDeclaringClass() {
                        return ci.getCachedClass();
                    }

                    @Override
                    protected Class[] getPT() {
                        return mm.getParameterTypes();
                    }

                    @Override
                    public Object invoke(Object object, Object[] arguments) {
                        try {
                            final Object value = mm.invoke(object, arguments);
                            // Do whatever you need with the value.
                            return value;
                        } catch (Exception ex) {
                            throw new RuntimeException(ex);
                        }
                    }
                });
            }

            mc = expando;
        } else if (GeneratedClosure.class.isAssignableFrom(theClass)) {
            mc = new ClosureMetaClass(registry, theClass);
        } else {
            mc = new MetaClassImpl(registry, theClass);
        }

        return mc;
    }
});
GroovySystem.getMetaClassRegistry().setMetaClassCreationHandle(新的ExpandoMetaClassCreationHandle()){
@凌驾
受保护的元类createNormalMetaClass(类、元类注册表){
最终列表propertyMethods=new ArrayList();
对于(方法:class.getDeclaredMethods()){
if(method.getReturnType()==themethodReturnTypeYouCareAllout.class){
属性方法。添加(方法);
}
}
最终元类mc;
if(propertyMethods.isEmpty()==false){
最终ExpandoMetaClass expando=新的ExpandoMetaClass(类,真,真);
对于(方法mm:属性方法){
final ClassInfo ci=ClassInfo.getClassInfo(mm.getDeclaringClass());
expando.addMetaMethod(新的MetaMethod(){
@凌驾
公共整型getModifiers(){
返回mm.getModifiers();
}
@凌驾
公共字符串getName(){
返回mm.getName();
}
@凌驾
公共类getReturnType(){
返回mm.getReturnType();
}
@凌驾
公共缓存类getDeclaringClass(){
返回ci.getCachedClass();
}
@凌驾
受保护类[]getPT(){
返回mm.getParameterTypes();
}
@凌驾
公共对象调用(对象,对象[]参数){
试一试{
最终对象值=mm.invoke(对象、参数);
//用这个值做你需要的任何事情。
返回值;
}捕获(例外情况除外){
抛出新的运行时异常(ex);
}
}
});
}
mc=expando;
}else if(GeneratedClosure.class.isAssignableFrom(类)){
mc=新的ClosureMetaClass(注册表,类);
}否则{
mc=新的元类impl(注册表,类);
}
返回mc;
}
});
这意味着我们将只为那些需要添加元方法的类创建Expando类