想要做以下事情:
BootStrap { def init = {servletContext -> ........ MyDomainClass.metaClass.save = {-> delegate.extraSave() //////// how to call original save() here? } } ......... }
P.S。 MyDomainClass#extraSave定义为public void extraSave(){.....}
答案 0 :(得分: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"
}
}
答案 1 :(得分:2)
为什么不为此目的利用GORM事件?在Domain类中:
def extraSave() {
// ...
}
def beforeInsert = {
extraSave()
}
def beforeUpdate = {
extraSave()
}
恕我直言,这是一个更清洁的方法。可以找到文档here
答案 2 :(得分:1)
不确定以下是否有效,但这可能是一个解决方案:
MyDomainClass.metaClass.origSave = MyDomainClass.metaClass.save
MyDomainClass.metaClass.save = {->
delegate.extraSave()
delegate.origSave()
}
如果以上工作,请给我feedbeck ......