【问题标题】:grails metaprogramming圣杯元编程
【发布时间】:2011-02-23 13:59:15
【问题描述】:

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

  1. init 关闭Bootstrap.groovy
  2. 插件的doWithDynamicMethods 闭包

我在这里提到的元编程应该在整个应用程序中都是可见的,典型的例子包括添加(或替换)第 3 方类的方法。

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 应用程序中不起作用?

【问题讨论】:

  • 很遗憾没有一个简单的答案...
  • (1) 仍然如此吗?我刚试过(只是一个简单的例子),一切似乎都很好(我可以更改控制器和引导程序本身,并且更改是热重新编译的)。

标签: grails groovy metaprogramming


【解决方案1】:

可以使用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 目录中。

【讨论】:

  • 我实际上只是想向String 类添加一个方法,所以这似乎有点过头了。我可能只是将它作为静态方法添加到我自己的StringUtils 类中,即使我更愿意将它作为String 的实例方法。据我所知,似乎没有任何简单可靠的方法可以在 Grails 应用程序中进行元编程,这令人惊讶。
  • 大概我不必使用 Gradle,例如我也可以使用 Maven 创建 JAR?
【解决方案2】:

查看Delegating MetaClass,它是 groovy 的一部分,使您的元类更改从一开始就用于该类的每个实例的元类的一部分。它按照简单的约定运行,甚至可以在 grails 之外运行。

【讨论】:

  • 我的问题是我应该在 Grails 应用程序的哪个位置应用元编程,而不是如何进行元编程本身。
  • 好吧,我明白了。这就是为什么我建议你应该做的地方是在一个名为 class 的约定中,它使你的更改/添加在整个 grails 应用程序中都可用,并且不会遇到将其放入 BootStrap 或其他一些“init”的问题" 在您需要时可能会或可能不会调用的方法。
【解决方案3】:

根据您的用例,Groovy AST transformations 是第三种选择。 AST 转换是在编译时对字节码的修改。它们从 Groovy 1.6 开始可用,并且在 Groovy 1.7 中得到了很大改进。特别是。 ASTBuilder 是一种非常优雅的方式。

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

【讨论】:

  • 感谢您的建议,但如果我只想在一个类中添加一些方法,这听起来有点矫枉过正。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-11-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-04-05
  • 2016-01-13
相关资源
最近更新 更多