我有几个使用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
答案 0 :(得分:1)
我不知道为什么在某些情况下只会调用你正在尝试的拦截,代码看起来很好。可能值得尝试以下一个或两个
将元编程从Bootstrap中移出并插入插件。我听说过这样的元编程总是应该在插件的doWithDynaicMethods
闭包中完成,而不是在Bootstrap中完成,因为在运行时重新加载应用程序时,不会(总是)执行Bootstrap。 / p>
不是通过在每个服务的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调用的服务。