Grails &引用;超载“;标准积垢法

Grails &引用;超载“;标准积垢法,grails,groovy,overloading,crud,Grails,Groovy,Overloading,Crud,要执行以下操作: BootStrap { def init = {servletContext -> ........ MyDomainClass.metaClass.save = {-> delegate.extraSave() //////// how to call original save() here? } } ......... } 引导{ def init={servletContext-> ........ MyDomainClass.m

要执行以下操作:

BootStrap { def init = {servletContext -> ........ MyDomainClass.metaClass.save = {-> delegate.extraSave() //////// how to call original save() here? } } ......... } 引导{ def init={servletContext-> ........ MyDomainClass.metaClass.save={-> delegate.extraSave() ////////如何在此处调用原始保存()? } } ......... }
p.S.MyDomainClass#extraSave定义为
public void extraSave(){…}

不确定以下是否有效,但这可能是一个解决方案:

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

请告诉我feedbeck,如果上述方法有效…

首先,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()
}

我认为这是一个更干净的方法。可以找到昨天尝试过的文档。说
origSave
是元类属性或其他东西而不是闭包之类的东西是行不通的。尝试了不同的调用方法:
origSave()
origSave.call()
此方法的一个缺点是需要将extraSave()添加到每个域类的事件处理程序中。元编程方法只需要在一个地方定义/调用extraSave()。当然,在处理这些事情时,我还是更喜欢基于EntityInterceptor的方法。重写GORM方法可以是真正的PITA.btw。要使用EntityInterceptor,只需创建org.hibernate.EmptyInterceptor的子类,并在grails app/conf/spring/resources.groovy中将其注册为名为“EntityInterceptor”的bean(由于grails 1.2,在旧版本中也可以这样做,但注册拦截器需要更多的工作)我甚至在尝试重载
save()
之前就尝试过这种方法。它的问题是,即使是在
save()
saveOrUpdate()
内部调用处理程序,所以我需要用
包装我的
extraSave()
。使用newsession
(这将导致其他问题,因为我正在进行一级批处理),或者考虑其他问题。