Groovy Mixins?

gab*_*iel 10 grails groovy mixins

我正在尝试在我的Groovy/Grails应用程序中混合使用一个类,并且我正在使用文档中定义的语法,但我一直收到错误.

我有一个看起来像这样的域类:

class Person {
  mixin(ImagesMixin)

  // ...
}
Run Code Online (Sandbox Code Playgroud)

编译很好,但由于某种原因,它将无法正常工作.包含ImagesMixin的文件位于我的/src/groovy/目录中.

我试过使用Groovy版本1.5.7和1.6-RC1没有任何运气.有谁知道我做错了什么?

堆栈跟踪:

2008-12-30 17:58:25.258::WARN:  Failed startup of context org.mortbay.jetty.webapp.WebAppContext@562791{/FinalTransmission,/home/kuccello/Development/workspaces/lifeforce/FinalTransmission/web-app}
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'pluginManager' defined in ServletContext resource [/WEB-INF/applicationContext.xml]: Invocation of init method failed; nested exception is java.lang.ExceptionInInitializerError
    at java.security.AccessController.doPrivileged(Native Method)
    at RunApp_groovy$_run_closure2_closure7.doCall(RunApp_groovy:67)
    at RunApp_groovy$_run_closure2_closure7.doCall(RunApp_groovy)
    at Init_groovy$_run_closure6.doCall(Init_groovy:131)
    at RunApp_groovy$_run_closure2.doCall(RunApp_groovy:66)
    at RunApp_groovy$_run_closure2.doCall(RunApp_groovy)
    at RunApp_groovy$_run_closure1.doCall(RunApp_groovy:57)
    at RunApp_groovy$_run_closure1.doCall(RunApp_groovy)
    at gant.Gant.dispatch(Gant.groovy:271)
    at gant.Gant.this$2$dispatch(Gant.groovy)
    at gant.Gant.invokeMethod(Gant.groovy)
    at gant.Gant.processTargets(Gant.groovy:436)
    at gant.Gant.processArgs(Gant.groovy:372)
Caused by: java.lang.ExceptionInInitializerError
    at java.lang.Class.forName0(Native Method)
    at java.lang.Class.forName(Class.java:169)
    at Episode.class$(Episode.groovy)
    at Episode.<clinit>(Episode.groovy)
    ... 13 more
Caused by: groovy.lang.MissingMethodException: No signature of method: static Person.mixin() is applicable for argument types: (java.lang.Class) values: {class ImagesMixin}
    at Broadcast.<clinit>(MyClass.groovy:17)
    ... 17 more
2008-12-30 17:58:25.259::WARN:  Nested in org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'pluginManager' defined in ServletContext resource [/WEB-INF/applicationContext.xml]: Invocation of init method failed; nested exception is java.lang.ExceptionInInitializerError:
groovy.lang.MissingMethodException: No signature of method: Person.mixin() is applicable for argument types: (java.lang.Class) values: {class ImagesMixin}
    at Broadcast.<clinit>(Person.groovy:17)
    at java.lang.Class.forName0(Native Method)
    at java.lang.Class.forName(Class.java:169)
    at Episode.class$(BelongsToMyClass.groovy)
    at Episode.<clinit>(BelongsToMyClass.groovy)
    at java.security.AccessController.doPrivileged(Native Method)
    at RunApp_groovy$_run_closure2_closure7.doCall(RunApp_groovy:67)
    at RunApp_groovy$_run_closure2_closure7.doCall(RunApp_groovy)
    at Init_groovy$_run_closure6.doCall(Init_groovy:131)
    at RunApp_groovy$_run_closure2.doCall(RunApp_groovy:66)
    at RunApp_groovy$_run_closure2.doCall(RunApp_groovy)
    at RunApp_groovy$_run_closure1.doCall(RunApp_groovy:57)
    at RunApp_groovy$_run_closure1.doCall(RunApp_groovy)
    at gant.Gant.dispatch(Gant.groovy:271)
    at gant.Gant.this$2$dispatch(Gant.groovy)
    at gant.Gant.invokeMethod(Gant.groovy)
    at gant.Gant.processTargets(Gant.groovy:436)
    at gant.Gant.processArgs(Gant.groovy:372)
2008-12-30 17:58:25.271::INFO:  Started SelectChannelConnector@0.0.0.0:8080
Run Code Online (Sandbox Code Playgroud)

Dón*_*nal 12

从Groovy 1.6开始,您可以在编译时将mixin应用于使用注释的类

@Mixin(ImagesMixin)
class Person {
}
Run Code Online (Sandbox Code Playgroud)

或者您可以在运行时应用mixin,如下所示:

def myMixin = ImagesMixin
Person.mixin myMixin
Run Code Online (Sandbox Code Playgroud)

后一种方法更具动态性,因为mixin的类可以在运行时确定.有关Groovy mixins的更多信息,请点击此处.

根据我的经验,很多域类的元编程根本不起作用.我不知道为什么,但怀疑它是由于这些类已经由Grails运行时进行了大量的元编程.一般来说,我的方法是

  • 在Groovy控制台中尝试POGO上的元编程
  • 如果可行,请在Grails控制台中的非域类上尝试
  • 如果可行,请在Grails控制台中的域类上尝试.如果它不起作用,那一定是因为它是一个域类(而不是语法问题).在这一点上,建议尝试找到另一种实现目标的方法.如果那是不可能的,那么使用Grails邮件列表和/或Stackoverflow和/或Grails源代码的组合来尝试使元编程工作.


Mat*_*lor 11

我认为你没有使用正确的mixin语法.试试这个:

class MyMixin {
    static doStuff(Person) {
        'stuff was done'
    }
}

class Person {}

Person.mixin MyMixin

new Person().doStuff()
Run Code Online (Sandbox Code Playgroud)


Sie*_*uer 4

我想您所看到的与其说是一个提案,不如说是一个功能;)Groovy 还不支持以这种方式开箱即用的 mixins(如果有的话)。但是有一个第三方库可以用来模拟这种行为:Injecto。mixin 可以使用 Groovy 1.6 版本(尚未最终版本)中的 AST-Macros 来定义。

您应该始终检查您正在阅读的文档是来自真正的 groovy 项目还是来自 GroovyJSR 项目(这是一个收集提案的地方)。

另一种方法是使用普通的 MOP 通过修改元类将行为注入到 Groovy 类中。

干杯