2

次のことをしたい:

ブートストラップ {
  def init = {servletContext ->
  .........
  MyDomainClass.metaClass.save = {->
     delegate.extraSave()
     //////// ここで元の save() を呼び出す方法は?
  }

}
.........
}

PS MyDomainClass#extraSave は次のように定義されますpublic void extraSave(){.....}

4

3 に答える 3

4

まず第一に、Bootstrap.groovyはこの種のメタプログラミングを行うのに最適な場所ではないかもしれません。このアプローチの問題は、アプリケーションの起動時にクラスへの変更が適用されることですが、アプリケーションを再ロードするとこれらの変更が失われる可能性があります。明らかに、これは開発中の問題であり、変更を加えるたびにサーバーを再起動してもかまわない場合はまったく問題になりませんが、これはすぐに大きな問題になると思います。アプリのリロード時にも変更を適用するには、メタプログラミングをプラグインに移動する必要があります。プラグインでは、onChangeアプリケーションのライフサイクルイベントにフックできます。

したがって、手順は次のとおりです。

  • プラグインを作成する
  • doWithDynamicMethodsプラグイン記述子のおよびonChangeクロージャでメタプログラミングを実行します

これは、すべてのコントローラークラスでchain()メソッドを「オーバーライド」する完全な例です。ドメインクラスのsave()メソッドに対して同様に行うコードは、いくつかの明らかな置換のみを必要とする必要があります。たとえば、application.domainClasses代わりに使用するapplication.controllerClasses

def doWithDynamicMethods = {ctx ->

    application.controllerClasses.each {controller ->
        replaceChain(controller)
    }
}

def onChange = {event ->
    if (application.isArtefactOfType(ControllerArtefactHandler.TYPE, event.source)) {
        def clz = application.getControllerClass(event.source?.name)
        replaceChain(clz)
    }
}

private replaceChain(controllerClass) {

    // Save a  reference to the grails chain() method
    def grailsChain = controllerClass.metaClass.pickMethod("chain", [Map] as Class[])

    controllerClass.metaClass.chain = {Map params ->

        println "My code to execute before chain goes here"

        // Invoke the grails chain() method
        grailsChain.invoke(delegate, [params] as Object[])

        println "My code to execute after chain goes here"
    }
}
于 2009-11-03T15:12:44.620 に答える
2

この目的で GORM イベントを活用しないのはなぜですか? ドメイン クラス:

def extraSave() {
    // ...
}

def beforeInsert = {
    extraSave()
}

def beforeUpdate = {
    extraSave()
}

私見これはよりクリーンなアプローチです。ドキュメントはここにあります

于 2009-11-03T15:41:14.347 に答える
1

以下が機能するかどうかはわかりませんが、これが解決策になる可能性があります。

MyDomainClass.metaClass.origSave = MyDomainClass.metaClass.save
MyDomainClass.metaClass.save = {-> 
   delegate.extraSave()
   delegate.origSave()
}

上記が機能した場合は、フィードバックをお願いします...

于 2009-11-03T08:55:12.163 に答える