You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过MetaClass拦截Script及其所有子类的方法调用?

Got it, let's walk through how to intercept all method calls on Script and its subclasses using MetaClass—we'll start with a Java implementation (since you preferred that) and then cover a more concise Groovy version if you need it.

Java Implementation

Since MetaClass is a Groovy-specific feature, we'll need to use Groovy's libraries in our Java code. Here's a step-by-step implementation:

Step 1: Add Groovy Dependency

First, make sure you have Groovy's core library in your project. For Maven, add this to your pom.xml:

<dependency>
    <groupId>org.codehaus.groovy</groupId>
    <artifactId>groovy-all</artifactId>
    <version>3.0.17</version> <!-- Use the latest stable version -->
</dependency>

Step 2: Create Custom MetaClass Interceptor

We'll extend MetaClassImpl and override invokeMethod to intercept calls. We'll specifically handle the evaluate method here, but you can expand this logic to cover other methods too.

import groovy.lang.MetaClassImpl;
import groovy.lang.Script;
import groovy.lang.Binding;
import groovy.lang.GroovyShell;

public class ScriptMethodInterceptor extends MetaClassImpl {

    private final GroovyShell shell;

    public ScriptMethodInterceptor(Class<?> targetClass, GroovyShell shell) {
        super(targetClass);
        this.shell = shell;
        initialize(); // Critical: Initialize the MetaClass to make it functional
    }

    @Override
    public Object invokeMethod(Object scriptInstance, String methodName, Object[] args) {
        // Intercept the "evaluate" method
        if ("evaluate".equals(methodName)) {
            System.out.println("Intercepted call to 'evaluate' method");
            // Run your custom logic here
            return runCustomEvaluation((String) args[0]);
        }
        // Delegate all other method calls to the original implementation
        return super.invokeMethod(scriptInstance, methodName, args);
    }

    private Object runCustomEvaluation(String scriptText) {
        // Implement your custom evaluation logic here
        Binding binding = new Binding();
        return shell.evaluate(scriptText, binding);
    }
}

Step 3: Apply the Interceptor to Script Class

Now we need to attach our custom MetaClass to the Script class so all its subclasses inherit this behavior:

public class Main {
    public static void main(String[] args) {
        GroovyShell shell = new GroovyShell();
        
        // Initialize our custom MetaClass
        ScriptMethodInterceptor customMetaClass = new ScriptMethodInterceptor(Script.class, shell);
        // Assign it to Script's metaClass property
        Script.metaClass = customMetaClass;
        
        // Test with a dynamic Script subclass
        String scriptCode = """
            def testMethod() { 
                println 'Test method executed'; 
                return 42; 
            }
        """;
        Script script = shell.parse(scriptCode);
        
        // This method call won't be intercepted
        script.invokeMethod("testMethod", new Object[]{});
        
        // This evaluate call will be intercepted
        script.invokeMethod("evaluate", new Object[]{"println 'Running evaluated script'"});
    }
}

Groovy Implementation

If you're working in a Groovy environment, the code becomes much more concise thanks to Groovy's syntax sugar and native MetaClass support:

import groovy.lang.Script
import groovy.lang.GroovyShell

// Define our custom MetaClass
def customMetaClass = new MetaClassImpl(Script.class) {
    private final GroovyShell shell = new GroovyShell()

    @Override
    Object invokeMethod(Object scriptInstance, String methodName, Object[] args) {
        if (methodName == "evaluate") {
            println "intercepted"
            // Run your custom logic here
            return shell.evaluate((String) args[0])
        } else {
            // Pass through other methods to the original implementation
            return super.invokeMethod(scriptInstance, methodName, args)
        }
    }
}
customMetaClass.initialize()

// Attach the MetaClass to Script
Script.metaClass = customMetaClass

// Test the interceptor
def testScript = new GroovyShell().parse("""
    def greet() { println 'Hello from script' }
""")

// Non-intercepted method call
testScript.greet()

// Intercepted evaluate call
testScript.evaluate("println 'Evaluated content'")

Key Notes

  • Global Impact: Setting the MetaClass on Script.class means all subclasses (including dynamically parsed scripts) will use this interceptor. If you only want to target specific subclasses, assign the MetaClass to those instead.
  • Initialize Method: Always call initialize() on your custom MetaClassImpl—this sets up internal state needed for proper method handling.
  • Flexibility: You can expand the interception logic to check for other method names, add logging, modify arguments, or even override return values as needed.

内容的提问来源于stack exchange,提问作者Scoopta

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 02:33:40