“重载”标准GORM CRUD方法

时间:2009-11-02 22:19:23

标签: grails groovy overloading crud

想要做以下事情:

BootStrap {
  def init = {servletContext ->
  ........
  MyDomainClass.metaClass.save = {-> 
     delegate.extraSave()
     //////// how to call original save() here?
  }

}
.........
}

P.S。 MyDomainClass#extraSave定义为public void extraSave(){.....}

3 个答案:

答案 0 :(得分:4)

首先,Bootstrap.groovy可能不是进行这种元编程的最佳位置。此方法的问题是,在应用程序启动时将应用对类的更改,但在重新加载应用程序时可能会丢失这些更改。显然这只是开发过程中的一个问题,如果您不介意每次进行更改时都不重新启动服务器,这根本不是问题,但我敢打赌,这很快就会成为一个主要的烦恼。为了在重新加载应用程序时应用更改,您应该将元编程移动到插件中,您可以在其中挂钩onChange应用程序生命周期事件。

所以步骤是:

  • 创建插件
  • 在插件描述符的doWithDynamicMethodsonChange闭包中进行元编程

这是一个完整的例子,我在所有控制器类上“覆盖”了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 ......