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

Groovy中如何实现可被子类继承的静态方法拦截以包装main方法?

实现方案说明

你的核心需求是不修改子类main方法的前提下,自动为其添加异常捕获与日志记录,原思路的问题在于Groovy中已存在的静态方法不会触发父类的invokeMethod拦截,只有当类找不到对应静态方法时才会调用该方法。下面提供两种可行的实现方式:

方案一:Groovy元编程动态包装(无需修改子类代码)

利用Groovy的元类(MetaClass)机制,在子类加载时动态替换其main方法,添加try/catch逻辑:

@Log4j2
class Wrapper {
    static {
        // 监听元类注册事件,处理所有继承Wrapper的子类
        MetaClassRegistry.metaClassRegistry.addMetaClassRegistryChangeEventListener { event ->
            def targetClazz = event.classToUpdate
            // 只处理Wrapper的子类,排除自身
            if (Wrapper.isAssignableFrom(targetClazz) && targetClazz != Wrapper) {
                // 获取子类原有的main方法
                def originalMain = targetClazz.metaClass.getStaticMethod('main', [String[]] as Class[])
                if (originalMain) {
                    // 替换为带异常捕获的版本
                    targetClazz.metaClass.static.main = { String[] args ->
                        try {
                            originalMain.invoke(null, args)
                        } catch (Throwable ex) {
                            log.error("未处理的异常抛出", ex)
                            // 可选:重新抛出异常以保留原有流程
                            throw ex
                        }
                    }
                }
            }
        }
    }
}

class Main extends Wrapper {
    static void main(String[] args) {
        throw new Exception("This should be logged.")
    }
}

// 测试调用
Main.main([] as String[])

原理说明

通过MetaClassRegistryChangeEventListener监听类加载事件,当子类(继承Wrapper)被加载时,动态替换其静态main方法为包装后的版本,既保留原方法逻辑,又自动添加异常日志。

方案二:模板方法模式(需调整子类代码结构)

如果允许子类将业务逻辑迁移到指定方法,可使用抽象父类定义模板方法,统一处理异常:

@Log4j2
abstract class Wrapper {
    static void main(String[] args) {
        try {
            // 调用子类实现的业务方法
            def targetClazz = currentClass()
            targetClazz.getMethod('runMain', String[].class).invoke(null, args)
        } catch (Throwable ex) {
            log.error("未处理的异常抛出", ex)
        }
    }

    // 子类需实现此方法返回自身类对象
    abstract static Class<?> currentClass()

    // 子类需将原main逻辑实现于此方法
    abstract static void runMain(String[] args)
}

class Main extends Wrapper {
    static Class<?> currentClass() {
        return Main.class
    }

    static void runMain(String[] args) {
        throw new Exception("This should be logged.")
    }
}

// 测试调用
Main.main([] as String[])

原理说明

父类定义统一的main入口,负责异常捕获与日志,子类只需实现业务逻辑方法runMain和返回自身类的方法,避免直接修改main的异常处理逻辑。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.15 19:03:14