在Grails中(至少到当前版本2.2),taglibs是闭包。对于某些taglib闭包,我想在拦截器中使用一些“around”类型的建议/封装闭包。
换句话说,让我们说直接来自Grails doc的这个taglib:
class SimpleTagLib {
def emoticon = { attrs, body ->
out << body() << (attrs.happy == 'true' ? " :-)" : " :-(")
}
}
现在,在不修改taglib代码的情况下,我想知道“表情符号”执行需要多长时间。
Spring AOP(以及我能找到的所有其他AOP)似乎只适用于Java方法 - 而taglib总是基于闭包。 “周围”切入点对于此非常完美,但我无法弄清楚如何使其有效。
答案 0 :(得分:1)
我写了一些类似的内容,我把它作为一个公共闭包放在一个类别中然后混合到服务中:
// 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:做了很多工作花了nn ms”并返回内部闭包的值作为doSomeWork
方法的返回值。
对于您的taglib实例,只需将out << ...
包装在
timer "Writing an emoticon", {
// your code
}
代码。
如果您不关心传递内部返回值,则可以返回作为闭包调用结果的持续时间。
<强>更新强>:
我可能误读了 - 你问的是如何在不修改taglib代码的情况下包装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
它还写入了日志。