4

Grails (少なくとも現在のバージョン 2.2 まで) では、taglib はクロージャーです。特定の taglib クロージャーについては、「アラウンド」タイプのアドバイスを使用したい / クロージャーをインターセプターでラップします。

別の言い方をすれば、Grails doc からそのままこの taglib があるとします。

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

ここで、taglib コードを変更せずに、「絵文字」の実行にかかる時間を計りたいと思います。

Spring AOP (および私が見つけることができる他のすべての AOP) は、Java メソッドでのみ機能するようです。また、taglibs は常にクロージャーに基づいています。これには「周りの」ポイントカットが最適ですが、それを機能させる方法がわかりません。

4

1 に答える 1

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: Doing a lot of work takes nn ms」のログ出力が得られ、メソッドの戻り値として内部クロージャーの値が返されますdoSomeWork

taglib インスタンスの場合out << ...は、

timer "Writing an emoticon", { 
    // your code
}

コード。

内部の戻り値を渡すことを気にしない場合は、代わりにクロージャ呼び出しの結果として期間を返すことができます。

更新

私は読み間違えたかもしれません.taglibコードをまったく変更せずにtaglib実行をラップする方法を尋ねていますか? body を受け取り、実行のために他の taglibs に渡すカスタム 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:

わかりましたので、試してみました。正常に動作します。最終的なコード (期間を返す 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

また、ログにも書き込みました。

于 2013-03-20T03:50:17.120 に答える