问题
I'm trying to create a generic function in grails that will allow me to specify a class and function name, and intercept any function calls based on that criteria:
getSomeClass().metaClass.invokeMethod = { String methodName, args ->
MetaMethod someAction = getSomeClass().metaClass.getMetaMethod(methodName, args)
def result = someAction.invoke(delegate, args)
if (methodName==getSomeMethodName())
intercept(args, result)
return result
}
This works for POGO, and domain classes, but does not seem to work for controller classes. While I'm fully aware there are Controller interceptors and filters available in Grails, these don't really centralise what I'm trying to achieve, and was trying to create a simple generic function for some centralised behaviour
Any guidance on why this doesn't work on Controllers would be appreciated, thanks
回答1:
Your approach will work for method calls that are made through the Groovy metaclass mechanism, but in Grails 2 this doesn't apply to controller actions - they're called using normal Java reflection (java.lang.reflect.Method.invoke
), and therefore your custom invokeMethod
is bypassed.
If you want an AOP mechanism that'll work for calls from Java as well as from Groovy you'll probably have to use something like AspectJ load-time weaving. Spring's proxy-based AOP may work but the Grails 2 controller system relies on the action methods having a particular @Action
annotation (which is added at compile time by an AST transformation) and I don't know whether Spring AOP proxies preserve method annotations from the target class on the generated proxy methods.
回答2:
Could it be that MyController.metaClass.invokeMethod
is overwritten by the grails framework after your definition?
Have you tried to check the content of MyController.metaClass.invokeMethod
through reflection?
来源:https://stackoverflow.com/questions/10956841/generic-method-interception-in-grails-specifically-controllers