替换invokeMethod以拦截Controller方法

时间:2014-06-26 13:27:46

标签: grails groovy

我希望通过替换ExpandoMetaClass的invokeMethod闭包来拦截所有控制器中的所有方法。

我创建了一个新的grails项目(2.3.5)。创建了一个名为AccountController的新Controller:

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

然后创建了另一个名为SecurityBootStrap的BootStrap:

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

我原以为:

Called method index
Index Called

提前致谢

1 个答案:

答案 0 :(得分:1)

您可以使用编译时元编程来执行此操作,但不能通过运行时元编程来执行此操作。 Groovy运行时元编程的一个限制是它只适用于从Groovy启动的方法调用。许多Grails框架都是用Java编写的。

示例:

class Widget {
    def getTheAnswer() {
        42
    }
}

Widget.metaClass.getTheAnswer = { ->
    2112
}

当Groovy代码调用new Widget().getTheAnswer()时,结果将是2112.当Java代码调用new Widget().getTheAnswer();时,结果将为42。