grails - 用于闭包的 Aspect(-like) 函数

标签 grails groovy aop taglib

在 Grails(至少到当前版本 2.2)中,标签库是闭包。对于某些 taglib 闭包,我想使用一些“环绕”类型的建议/将闭包包装在拦截器中。

换句话说,假设直接来自 Grails 文档的 taglib:

class SimpleTagLib {
   def emoticon = { attrs, body ->
      out << body() << (attrs.happy == 'true' ? " :-)" : " :-(")
   }
}

现在,在不修改 taglib 代码的情况下,我想计算“表情符号”的执行时间。

Spring AOP(以及我能找到的所有其他 AOP)似乎只适用于 Java 方法——而标记库总是基于闭包。一个“环绕”切入点将是完美的,但我不知道如何使它工作。

最佳答案

我写了一些类似的东西,我把它作为一个公共(public)关闭放在一个类别中,然后混合到服务中:

// 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()
        }
    }
 }

这将为您提供 的日志输出“警告:做很多工作需要 nn 毫秒”并返回内部闭包的值作为 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

它还写入日志。

关于grails - 用于闭包的 Aspect(-like) 函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15489915/

相关文章:

javascript - Groovy Grails 发送/接收变量

java - 除了一个子包,我如何在整个包上应用 aop

grails - 在 GSP 中呈现 HTML

java - 直接 Java 和 Grails 之间的反射差异

Groovy 常量字符串作为注释值

java - 如何在方面内可靠地 Autowiring 成员 - 即使在上下文刷新之后?

java - 如何在 Spring 3 中使用纯注释从接口(interface)生成代理类?

forms - 将_form.gsp模板从Grails 2导入到Grails3

plugins - Grails Maven依赖解析

grails - 如何自动将在 resources.groovy 中声明的 Grails 组件注入(inject)到我的 IntegrationSpecs 中?