次のことをしたい:
ブートストラップ { def init = {servletContext -> ......... MyDomainClass.metaClass.save = {-> delegate.extraSave() //////// ここで元の save() を呼び出す方法は? } } ......... }
PS MyDomainClass#extraSave は次のように定義されますpublic void extraSave(){.....}
次のことをしたい:
ブートストラップ { def init = {servletContext -> ......... MyDomainClass.metaClass.save = {-> delegate.extraSave() //////// ここで元の save() を呼び出す方法は? } } ......... }
PS MyDomainClass#extraSave は次のように定義されますpublic void extraSave(){.....}
まず第一に、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"
}
}
この目的で GORM イベントを活用しないのはなぜですか? ドメイン クラス:
def extraSave() {
// ...
}
def beforeInsert = {
extraSave()
}
def beforeUpdate = {
extraSave()
}
私見これはよりクリーンなアプローチです。ドキュメントはここにあります
以下が機能するかどうかはわかりませんが、これが解決策になる可能性があります。
MyDomainClass.metaClass.origSave = MyDomainClass.metaClass.save
MyDomainClass.metaClass.save = {->
delegate.extraSave()
delegate.origSave()
}
上記が機能した場合は、フィードバックをお願いします...