How can I intercept execution of all the methods in a Java application using Groovy?

拟墨画扇 提交于 2019-12-07 04:58:53

问题


Is it possible to intercept all the methods called in a application? I'd like to do something with them, and then let them execute. I tried to override this behaviour in Object.metaClass.invokeMethod, but it doesn't seem to work.

Is this doable?


回答1:


Have you looked at Groovy AOP? There's very little documentation, but it allows you to define pointcuts and advice in a conceptually similar way as for AspectJ. Have a look at the unit tests for some more examples

The example below will match all calls to all woven types and apply the advice before proceeding:

// 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



回答2:


First of all, overriding Object.metaClass.invokeMethod doesn't work because when Groovy tries to resolve a method call for a type X, it checks the metaClass of X, but not the metaClass of its parent class(es). For example, the following code will print "method intValue intercepted"

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

6.intValue()

// Reset the metaClass  
Integer.metaClass = null  

But this code will not:

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

6.intValue()

// Reset the metaClass  
Object.metaClass = null

Your question was "Is it possible to intercept all the methods called in a application?", but could you be a bit more precise about whether you want to:

  • Intercept calls to Groovy methods, Java methods, or both
  • Intercept calls to only your Groovy/Java methods or also intercept calls to Groovy/Java library classes

For example, if you only want to intercept calls to your Groovy classes, you could change your classes to implement GroovyInterceptable. This ensures that invokeMethod() is invoked for every method called on those classes. If the nature of the interception (i.e. the stuff you want to do before/after invoking the called method) is the same for all classes, you could define invokeMethod() in a separate class and use @Mixin to apply it to all your classes.

Alternatively, if you also want to intercept calls to Java classes, you should check out the DelegatingMetaClass.



来源:https://stackoverflow.com/questions/1226821/how-can-i-intercept-execution-of-all-the-methods-in-a-java-application-using-gro

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!