gpt4 book ai didi

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

转载 作者:行者123 更新时间:2023-12-03 23:06:03 24 4
gpt4 key购买 nike

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

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

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

我怎样才能在 groovy 中做到这一点?或者他们可能是实现我尝试做的事情的另一种方式?

最佳答案

像下面这样的东西会做吗?使用 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)

    关于reflection - Groovy:在调用任何方法之前和之后执行代码透明,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22868987/

    24 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com