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
相关产品推荐
相关产品推荐

