2009-11-02 24 views
2

想做到以下几点:“重载” 标准格姆CRUD方法

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

} 
......... 
} 

附: MyDomainClass#extraSave被定义为public void extraSave(){.....}

回答

1

不知道下面的工作,但是这可能是一个解决办法:

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

请给我feedbeck如果上述工作...

+0

昨天试过了。不起作用,说'origSave'是元类属性或东西,而不是闭包,就像那样。尝试不同的方式来调用它:'origSave()'和'origSave.call()' – Archer 2009-11-03 10:16:46

+1

正确的代码在这里:http://stackoverflow.com/a/8388366/207791 – 2012-08-10 06:57:19

4

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

因此,步骤是:

  • 创建插件
  • 不要在插件描述

这里的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" 
    } 
} 
2

为什么不利用这个目的的GORM事件?在域类:

def extraSave() { 
    // ... 
} 

def beforeInsert = { 
    extraSave() 
} 

def beforeUpdate = { 
    extraSave() 
} 

恕我直言,这是一个更清洁的方法。可以找到文档here

+0

这种方法的缺点是,你需要添加extraSave()用于每个域类的事件处理程序。元编程方法只需要你在一个地方定义/调用extraSave() – 2009-11-03 17:46:34

+0

当然,在处理这些事情时,我仍然更喜欢基于EntityInterceptor的方法。重写GORM方法可以是一个真正的PITA。 – 2009-11-03 18:41:02

+1

btw。因为使用EntityInterceptor只需创建一个org.hibernate.EmptyInterceptor的子类,并将它注册为一个名为“entityInterceptor”的bean,在你的grails-app/conf/spring/resources.groovy 中(因为Grails 1.2 - 也可能在旧版本中,但拦截器的注册是更多的工作) – 2009-11-03 18:46:05