Groovy:在调用任何方法之前和之后透明地执行代码

Posted

技术标签:

【中文标题】Groovy:在调用任何方法之前和之后透明地执行代码【英文标题】:Groovy: Execute Code transparent before and after any method is invoked 【发布时间】:2014-05-17 03:10:42 【问题描述】:

假设我们有一个带有一些方法(静态或非静态)的 groovy 类。 我想要做的是在调用这个类的每个方法之前和之后执行一些代码,而不需要完全触及类,也不需要动态操作每个方法内部的代码。

我尝试使用 groovy 元类;获取元类的所有方法,然后用包装方法动态替换每个方法,包含一些代码并在中间调用旧方法。问题是,我不知道每个原始方法的参数,所以我不能用新方法(闭包)替换旧方法,因为我不能动态创建具有不同数量和类型参数的包装闭包,即使你可以,我不知道如何在包装封闭内访问它们。我需要包装闭包具有与旧方法相同的签名,以便在类被透明更改后有人尝试调用旧方法时调用闭包。

javascript 例如我可以使用 args[] 数组来访问函数体中的所有参数,即使我在编写代码时不知道参数名称。

我如何在 groovy 中做到这一点?还是他们可能是实现我尝试做的另一种方式?

【问题讨论】:

【参考方案1】:

像下面这样的东西会做吗?使用invokeMethod 拦截对每个方法的调用。测试是不言自明的。

说明:

下面的元类实现覆盖来自GroovyObject 的invokeMethod。由于所有 groovy 对象都继承自 GroovyObject,我们获得了操作/拦截方法调用的灵活性,甚至可以指定我们自己的 methodMissing 实现。我们需要一个覆盖静态方法和一个非静态方法。基本上,invokeMethod 拦截对定义它的类上的每个方法的调用。我们最终为每种方法提供了一些 beforeafter 功能。使用反射,下面的实现能够通过名称和参数找出方法并在运行时调用它。

注意:-

确保方法调用的返回值也从闭包返回 可能是一个昂贵的类具有大量实现的方法 如果需要选择性执行,则检查方法名,然后拦截调用

实施:

class Dummy 
    def method1()  System.out.println "In method 1" 
    def method2(String str)  System.out.println "In method 2" 
    static def method3(int a, int b)  
        System.out.println "In static method 3" 
        


Dummy.metaClass.invokeMethod = String name, args ->
   def result

   System.out.println(
     "Do something before $name is called with args $args")

   try 
      result = delegate.metaClass.getMetaMethod(name, args)
                                 .invoke(delegate, args)
    catch(Exception e) 
       System.out.println "Handling exception for method $name"
   

   System.out.println(
      "Do something after $name was called with args $args \n")

   result


Dummy.metaClass.'static'.invokeMethod = String name, args ->
   def result

   System.out.println(
     "Do something before static method $name is called with args $args")

   try 
      result = delegate.metaClass.getMetaMethod(name, args)
                                 .invoke(delegate, args)
    catch(Exception e) 
       System.out.println "Handling exception for method $name"
   

   System.out.println(
     "Do something after static method $name was called with args $args \n")

   result


def dummy = new Dummy()
dummy.method1()
dummy.method2('Test')
Dummy.method3(1, 2)

【讨论】:

以上是关于Groovy:在调用任何方法之前和之后透明地执行代码的主要内容,如果未能解决你的问题,请参考以下文章

Groovy踩坑记之方法调用八层认识

Groovy闭包 Closure ( 闭包调用 | 闭包默认参数 it | 代码示例 )

如何正确地从 groovy 调用 shell 命令

[ jquery 效果 fadeTo([speed,[easing],[fn]]) ] 此方法用于通过调整不透明度的变化至指定目标来实现所有匹配元素的淡入效果,并在动画完成后可选地触发一个回调函数(代

在每个 Alamofire 请求之前/之后调用一个函数

在调用 f:ajax 侦听器之前和之后执行 JavaScript