【问题标题】:How can I intercept execution of all the methods in a Java application using Groovy?如何使用 Groovy 拦截 Java 应用程序中所有方法的执行?
【发布时间】:2010-11-16 15:26:35
【问题描述】:

是否可以拦截应用程序中调用的所有方法?我想对他们做点什么,然后让他们执行。我试图在Object.metaClass.invokeMethod 中覆盖此行为,但它似乎不起作用。

这可行吗?

【问题讨论】:

  • 这可能不是一个好主意。你想完成什么?

标签: groovy metaprogramming language-features aop interceptor


【解决方案1】:

首先,覆盖 Object.metaClass.invokeMethod 不起作用,因为当 Groovy 尝试解析类型 X 的方法调用时,它会检查 X 的元类,而不是其父类的元类。比如下面的代码会打印“method intValue intercepted”

Integer.metaClass.invokeMethod = {def name, def args ->
  System.out.println("method $name intercepted")
}

6.intValue()

// Reset the metaClass  
Integer.metaClass = null  

但是这段代码不会:

Object.metaClass.invokeMethod = {def name, def args ->
  System.out.println("method $name intercepted")
}

6.intValue()

// Reset the metaClass  
Object.metaClass = null

您的问题是“是否可以拦截应用程序中调用的所有方法?”,但您能否更准确地了解您是否想要:

  • 拦截对 Groovy 方法、Java 方法或两者的调用
  • 仅拦截对您的 Groovy/Java 方法的调用,或者也拦截对 Groovy/Java 库类的调用

例如,如果您只想拦截对 Groovy 类的调用,您可以更改您的类以实现 GroovyInterceptable。这确保为这些类上调用的每个方法调用 invokeMethod()。如果拦截的性质(即在调用被调用方法之前/之后您想要做的事情)对于所有类都是相同的,您可以在一个单独的类中定义 invokeMethod() 并使用 @Mixin 将它应用于您的所有类。

或者,如果您还想拦截对 Java 类的调用,您应该查看DelegatingMetaClass。

【讨论】:

  • 我希望能够拦截 Groovy 和 Java 方法调用。
  • 那么你应该使用 DelegatingMetaClass 或成熟的 AOP 框架,例如 groovy-aop 或 AspectJ
  • 你不能用元类拦截所有方法调用,因为从Java调用的Java方法不会通过Groovy调度。因此,如果您有一个 Java 类调用另一个 Java 类,则如果不使用某种 AOP 或类似的东西,您将无法拦截该调用。
【解决方案2】:

你看过Groovy AOP吗? documentation 很少,但它允许您以与 AspectJ 类似的概念方式定义切入点和建议。查看unit tests 了解更多示例

以下示例将匹配对所有编织类型的所有调用并在继续之前应用建议:

// aspect MyAspect
class MyAspect {
  static aspect = {
    //match all calls to all calls to all types in all packages
    def pc = pcall("*.*.*")

    //apply around advice to the matched calls
    around(pc) { ctx ->
      println ctx.args[0]
      println ctx.args.length
      return proceed(ctx.args)
    }
  }
}
// class T
class T {
  def test() {
    println "hello"
  }
}
// Script starts here
weave MyAspect.class
new T().test()
unweave MyAspect.class

【讨论】:

    猜你喜欢
    • 2018-06-08
    • 2013-05-23
    • 2012-08-29
    • 1970-01-01
    • 1970-01-01
    • 2023-03-14
    • 2015-01-31
    • 2014-03-25
    • 2012-03-12
    相关资源
    最近更新 更多