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