grails metaprogramming
My understanding is that there are two obvious places in a Grails app where one can do meta-programming:
init
closure of Bootstrap.groovy
doWithDynamicMethods
closure of a plugin The meta-programming I'm referring to here should be visible throughout the application, typical examples include adding (or replacing) methods of 3rd party classes.
String.metaClass.myCustomMethod = { /* implementation omitted */ }
The disadvantage of (1), is that the metaprogramming won't be applied when the application is dynamically reloaded. The disadvantage of (2) is that I need to create and maintain an entire plugin just for the sake of a little metaprogramming.
Is there a better place to do this kind of metaprogramming?
Update
Following Ted's suggestion below, I added the following class to src/groovy
package groovy.runtime.metaclass.java.lang
/**
* Adds custom methods to the String class
*/
class StringMetaClass extends DelegatingMetaClass {
StringMetaClass(MetaClass meta) {
super(meta)
}
Object invokeMethod(Object object, String method, Object[] arguments) {
if (method == 'hasGroovy') {
object ==~ /.*[Gg]roovy.*/
} else {
super.invokeMethod object, method, arguments
}
}
}
Then restarted the app and ran the following code in the Grails console:
assert 'mrhaki loves Groovy'.hasGroovy()
I got the following exception
groovy.lang.MissingMethodException: No signature of method:
java.lang.String.hasGroovy() is applicable for argument types: () values: []
Am I doing something wrong or is there a reason this doesn't work in a Grails app?
Check out the Delegating MetaClass, it's part of groovy and makes your metaclass changes part of the metaclass that's used on every instance of that class right from the start. It operates on a simple convention and even works outside of grails.
Depending on your use case, Groovy AST transformations are a third option. AST transformation are modifications of the bytecode at compile time. They are available since Groovy 1.6 and have been improved a lot in Groovy 1.7. Esp. ASTBuilder is a very elegant way.
Be aware that using AST within Grails might require some modifications to the build. The classes performing the AST must be compiled before the classes that are subject to AST. This could be easily done by hooking into the "CompileStart" event in scripts/_Events.groovy and precompile the Transformation first.
You can use the DelegatingMetaClass solution, but it needs to be packaged in a JAR file and then added to the lib directory.
Create a new directory with the following Gradle build file:
apply plugin: 'groovy'
repositories.mavenCentral()
dependencies { groovy: 'org.codehaus.groovy:groovy-all:1.8.6' }
In the src/main/groovy directory you can place the StringMetaClass source code. With $ gradle jar you can create a JAR file and then copy it to the lib directory of your Grails application.
链接地址: http://www.djcxy.com/p/45902.html上一篇: 如何理解其他人的CSS架构?
下一篇: grails元编程