2014-06-26 22 views
0

我想通過替換ExpandoMetaClass的invokeMethod閉包來攔截所有控制器中的所有方法。替換invokeMethod來攔截控制器方法

我創建了一個新的grails項目(2.3.5)。創建一個新的控制器,叫的AccountController:

package com.invoke.test 
class AccountController { 
    def index() { 
     System.out.println("Index Called") 
    } 
} 

然後創建一個名爲SecurityBootStrap一個額外的自舉:

class SecurityBootStrap { 

def grailsApplication 

def verifyMethodAccess = { String name, args -> 
    log.info "Called method ${name}" 
    def method = delegate.metaClass.getMetaMethod(name, args) 
    if (method) { 
     return method.invoke(delegate, args) 
    } 
    return null 
} 

def init = { servletContext -> 
    grailsApplication.controllerClasses.each { controllerClass -> 
     controllerClass.clazz.metaClass.invokeMethod = verifyMethodAccess 
     log.info "Replaced the invokeMethod closure on ${controllerClass.clazz}" 
    } 
} 
} 

啓動應用程序後,日誌是尋找有前途:

|Running Grails application 
2014-06-26 15:07:26,476 [localhost-startStop-1] INFO conf.SecurityBootStrap - Replaced the invokeMethod closure on class grails.plugin.databasemigration.DbdocController 
2014-06-26 15:07:26,477 [localhost-startStop-1] INFO conf.SecurityBootStrap - Replaced the invokeMethod closure on class com.invoke.test.AccountController 
|Server running. Browse to http://localhost:8080/InvokeTest 

但是,當致電http://localhost:8080/InvokeTest/account/index日誌看起來像:

Index Called 

我希望它是:提前

回答

1

你可以用編譯時元編程做這個

Called method index 
Index Called 

謝謝,但你不能運行時元編程做到這一點。 Groovy的運行時元編程的侷限性在於,它僅適用於從Groovy啓動的方法調用。大部分的Grails框架都是用Java編寫的。

實施例:

class Widget { 
    def getTheAnswer() { 
     42 
    } 
} 

Widget.metaClass.getTheAnswer = { -> 
    2112 
} 

當Groovy代碼調用new Widget().getTheAnswer()結果將是2112當Java代碼調用new Widget().getTheAnswer();結果將是42

+0

我添加另一種方法來控制,'DEF methodTwo( ){println「MethodTwo Called」}'並在index()中調用它。 methodTwo()現在應該通過'invokeMethod'調用,因爲它是從groovy調用的,對吧?但日誌只顯示「MethodTwo Called」。 – Marcin

+0

即使對於Groovy類(絕對不適用於Java類),我認爲您的方法也不會起作用。我認爲你的類必須實現GroovyInterceptable,以調用現有的方法被invokeMethod攔截。 –