grails元编程

grails元编程,grails,groovy,metaprogramming,Grails,Groovy,Metaprogramming,我的理解是,Grails应用程序中有两个明显的地方可以进行元编程: Bootstrap.groovy的init闭包 插件的doWithDynamicMethods关闭 我在这里提到的元编程应该在整个应用程序中都可见,典型的例子包括添加(或替换)第三方类的方法 String.metaClass.myCustomMethod = { /* implementation omitted */ } (1)的缺点是,当动态重新加载应用程序时,不会应用元编程。(2)的缺点是我需要创建和维护一个完整的插件,

我的理解是,Grails应用程序中有两个明显的地方可以进行元编程:

  • Bootstrap.groovy的
    init
    闭包
  • 插件的
    doWithDynamicMethods
    关闭
  • 我在这里提到的元编程应该在整个应用程序中都可见,典型的例子包括添加(或替换)第三方类的方法

    String.metaClass.myCustomMethod = { /* implementation omitted */ }
    
    (1)的缺点是,当动态重新加载应用程序时,不会应用元编程。(2)的缺点是我需要创建和维护一个完整的插件,只是为了一点元编程

    有更好的地方来做这种元编程吗

    更新 根据下面Ted的建议,我将以下类添加到
    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
            }
        }
    }
    
    然后重新启动应用程序并在Grails控制台中运行以下代码:

    assert 'mrhaki loves Groovy'.hasGroovy()
    
    我得到了以下例外

    groovy.lang.MissingMethodException: No signature of method:
    java.lang.String.hasGroovy() is applicable for argument types: () values: []
    

    是我做错了什么,还是有什么原因使它在Grails应用程序中不起作用?

    根据您的使用情况,是第三种选择。AST转换是在编译时对字节码的修改。它们从Groovy1.6开始提供,并且在Groovy1.7中得到了很大改进。尤其是ASTBuilder是一种非常优雅的方式


    请注意,在Grails中使用AST可能需要对构建进行一些修改。执行AST的类必须在受AST约束的类之前编译。这可以通过挂接scripts/_Events.groovy中的“CompileStart”事件并首先预编译转换来轻松完成。

    检查,它是groovy的一部分,并使您的元类从一开始就更改该类的每个实例上使用的元类的一部分。它在一个简单的约定上运行,甚至在grails之外工作。

    您可以使用DelegatingMetaClass解决方案,但它需要打包在一个JAR文件中,然后添加到lib目录中

    使用以下Gradle生成文件创建新目录:

    apply plugin: 'groovy'
    repositories.mavenCentral()
    dependencies { groovy: 'org.codehaus.groovy:groovy-all:1.8.6' }
    

    在src/main/groovy目录中,可以放置StringMetaClass源代码。使用$gradle jar,您可以创建一个jar文件,然后将其复制到Grails应用程序的lib目录中。

    谢谢您的建议,但如果我只是想向类添加一些方法,这听起来有些过分。我的问题是在Grails应用程序中应该在何处应用元编程,而不是如何进行元编程本身。对,我明白。这就是为什么我建议您应该在一个名为class的约定中进行更改/添加,该约定使您的更改/添加在整个grails应用程序中都可用,并且不会遇到将其放入引导或其他“init”的问题方法,该方法在您需要时可能已被调用,也可能未被调用。遗憾的是,没有一个简单的答案…是否(1)仍然如此?我只是尝试了一下(只是一个简单的例子),一切似乎都还可以(我可以更改控制器和引导程序本身,并且更改是热重新编译的)。我实际上只是想向
    String
    类添加一个方法,所以这似乎有些过分了。我可能只是将它作为一个静态方法添加到我自己的
    StringUtils
    类中,尽管我更喜欢将它作为
    String
    的实例方法。据我所知,在Grails应用程序中似乎没有任何简单可靠的元编程方法,这令人惊讶。大概我不必使用Gradle,例如,我也可以使用Maven来创建JAR?