使用groovy / grails中的元编程拦截服务方法调用

时间:2010-02-11 20:20:55

标签: flex grails groovy metaprogramming

我有几个使用Spring BlazeDS集成从Flex代码调用的Grails服务。我想使用groovy metaClass添加一些常规调试日志记录。我在bootstrap类中有以下内容:

class MyBootStrap {

def grailsApplication

def init = { servletContext ->
        initServiceCallLogging()
}

def destroy = {
}

private def initServiceCallLogging() {
    grailsApplication.serviceClasses.each { serviceClass ->
        serviceClass.metaClass.invokeMethod = { name, args ->
            log.debug "Method $name invoked"
            def metaMethod = delegate.metaClass.getMetaMethod(name, args)
            def result = metaMethod.invoke(delegate, args)
            return result

        }
    }
}
}

只要从例如调用Service方法调用Service方法,这就可以正常工作。 Grails控制器或服务但是当从Flex直接调用时(通过BlazeDS),方法调用不会被截获。

任何人都知道如何解决这个问题,或者这是不是可以通过元编程实现,并且应该使用Spring AOP吗?

THX

3 个答案:

答案 0 :(得分:1)

我不知道为什么在某些情况下只会调用你正在尝试的拦截,代码看起来很好。可能值得尝试以下一个或两个

建议1

将元编程从Bootstrap中移出并插入插件。我听说过这样的元编程总是应该在插件的doWithDynaicMethods闭包中完成,而不是在Bootstrap中完成,因为在运行时重新加载应用程序时,不会(总是)执行Bootstrap。 / p>

建议2

不是通过在每个服务的metaClass上实现invokeMethod来拦截方法,而是直接在每个类上实现invokeMethod,并使服务实现GroovyInterceptable。例如,替换:

class MyService {
// implementation
}

使用:

class MyService implements GroovyInterceptable {

  def invokeMethod(String name, args) {
    log.debug "Method $name invoked"

    def originalMethod = Car.metaClass.getMetaMethod(name, args)
    originalMethod.invoke(this, args)
  }
}

这个问题的一个明显问题是,它将要求您添加上述样板,以及所有服务。但如果它有效,也许您可​​以将它作为DRYer解决方案的起点。

答案 1 :(得分:1)

这对我有用。也许是因为新版本的BlazeDS插件。

一个建议: 而不是写

log.debug` "Method $name invoked

我用:

delegate.log.debug "Service call: ${name}(${args})"

优点是记录器编写了发生日志记录的类而不是bootstrap。

答案 2 :(得分:0)

我遇到的another problem解决方案,也解决了这个问题。在flex-servlet.xml中使用显式的服务定义而不是@RemotingDestination注释,元编程也适用于从BlazeDS调用的服务。