在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方法 – 而taglibs总是基于闭包.一个“周围”的切入点对于这个来说是完美的,但我无法弄清楚如何让它发挥作用.
解决方法
我写了类似的东西,我把它作为一个公共关闭在一个类别然后混合到服务:
// 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 } }
在其他类中,您只需引用计时器闭包:
@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,它接受正文并将其传递给其他taglibs执行?
我没试过这个,但是有点像:
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
它还写入了日志.