闭包的Aspect(类似)函数

时间:2013-03-19 01:21:11

标签: grails groovy aop taglib

在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总是基于闭包。 “周围”切入点对于此非常完美,但我无法弄清楚如何使其有效。

1 个答案:

答案 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

它还写入了日志。