我写了一些类似的东西,我把它作为一个公共关闭放在一个类别中,然后混合到服务中:
// TimingCategory.groovy
/**
* Provides common AOP timing functionality to Services which mixin this category.
*/
class TimingCategory {
static Closure timer = { String label = "The call", Closure closure ->
Long start = System.currentTimeMillis()
def result = closure.call()
Long end = System.currentTimeMillis()
Long duration = end - start
log.warn "${label} took ${duration} ms"
return result
}
}
在其他类中,您只需像这样引用timer
闭包:
@Mixin(TimingCategory)
public class WhateverService {
public String doSomeWork() {
timer "Doing a lot of work", {
1000.times { doSomething() }
someMethodWithAStringReturnValue()
}
}
}
这将为您提供“WARN: Doing a lot of work take nn ms”的日志输出,并返回内部闭包的值作为doSomeWork
方法的返回值。
对于您的 taglib 实例,只需out << ...
将
timer "Writing an emoticon", {
// your code
}
代码。
如果您不关心传递内部返回值,则可以改为返回持续时间作为闭包调用的结果。
更新:
我可能读错了——你问的是如何在不修改 taglib 代码的情况下包装 taglib 执行?如何创建一个接受主体并将其传递给其他标记库执行的自定义标记库?
我没有尝试过,但类似:
class TimedTagLib {
static namespace = "timer"
def timedTag = { attrs, body ->
timer "Executing the timed tag", {
out << body()
}
}
}
并像调用它一样
<timer:timedTag><g:emoticon whatever="something">Text</g:emoticon></timer:timedTag>
更新 2:
好的,所以我试了一下。工作正常。我的最终代码(我添加了第二个返回持续时间的计时器闭包):
// TimedTagLib.groovy
@Mixin(TimingCategory)
class TimedTagLib {
static namespace = "timer"
def timedTag = { attrs, body ->
def duration = returnTimer "Printing the timed tag", {
out << body()
}
out << "Took ${duration} ms to print"
}
}
和观点:
// someView.gsp
<timer:timedTag>
<g:formatLocalDate date="${LocalDate.now()}" />
</timer:timedTag>
生成的 HTML 是:
03/19/2013
Took 6 ms to print
它还写入日志。