拦截Groovy中所有元类的所有方法调用
我试图拦截在Java环境中运行的Groovy脚本内的所有方法调用。拦截Groovy中所有元类的所有方法调用
特别是我想检查所有方法调用的返回类型,如果它是X
我想用Y
替换它。
我知道你可以在MetaClass上使用invokeMethod
进行截取,但我只能对我编译的脚本类做到这一点。如果脚本依次调用类A
上的方法,那么它将创建一个新的MetaClass[A]
,如果没有手动从注册表中手动获取该MetaClass并使用元方法覆盖MetaClass,则无法拦截。
我曾尝试使用GroovySystem.getMetaClassRegistry()
为创建MetaClasses时添加侦听器,以在其中添加元方法,但它似乎从不触发。
我希望这是自动的,而不是事先必须添加注释到我应该转换的方法,或知道哪些类的方法我想转换。返回X
的所有方法应返回Y
。
我可以全局拦截所有方法调用吗?
我可以拦截MetaClass创建吗?
我可以添加自动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;
}
});
这意味着我们将只为那些需要添加meta方法的人创建Expando类。
以上是 拦截Groovy中所有元类的所有方法调用 的全部内容, 来源链接: utcz.com/qa/264347.html