2009-11-02 23 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