想要执行以下操作:
引导程序 { def init = {servletContext -> ........... MyDomainClass.metaClass.save = {-> 委托.extraSave() //////// 如何在这里调用原始的 save()? } } ………… }
PS MyDomainClass#extraSave 定义为public void extraSave(){.....}
想要执行以下操作:
引导程序 { def init = {servletContext -> ........... MyDomainClass.metaClass.save = {-> 委托.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()
}
如果上述方法有效,请给我反馈...