Groovy 混合?
我正在尝试在 Groovy/Grails 应用程序中混合一个类,并且我正在使用 文档中定义的语法,但我不断收到错误。
我有一个如下所示的域类:
class Person {
mixin(ImagesMixin)
// ...
}
它编译得很好,但由于某种原因它无法工作。 包含 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 [email protected]:8080
I'm trying to mix-in a class in my Groovy/Grails app, and I'm using the syntax defined in the docs, but I keep getting an error.
I have a domain class that looks like this:
class Person {
mixin(ImagesMixin)
// ...
}
It compiles fine, but for some reason it won't work. The file containing ImagesMixin is located in my /src/groovy/
directory.
I've tried it using Groovy versions 1.5.7 and 1.6-RC1 without any luck. Does anyone know what I'm doing wrong?
stacktrace:
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 [email protected]:8080
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(7)
从 Groovy 1.6 开始,您可以使用注释在编译时将 mixin 应用于类,
也可以在运行时应用 mixin,如下所示:
后一种方法更加动态,因为可以在运行时确定要 mixin 的类。 有关 Groovy mixins 的更多信息,请访问此处。
根据我的经验,域类的许多元编程根本不起作用。 我不太清楚为什么,但怀疑这是因为这些类已经由 Grails 运行时进行了大量的元编程。 一般来说,我的方法是
Since Groovy 1.6 you can either apply a mixin at compile-time to a class using an annotation
Or you can apply the mixin at runtime like this:
The latter approach is more dynamic as the class to mixin can be determined at runtime. Further information about Groovy mixins is available here.
In my experience, a lot of meta-programming of domain classes simply doesn't work. I don't exactly know why, but suspect it's due to the fact these classes are already very heavily meta-programmed by the Grails runtime. In general my approach is
我认为您没有使用正确的 mixin 语法。 尝试这个:
I don't think you are using the proper mixin syntax. Try this:
我想您所看到的与其说是一个提案,不如说是一个功能;)Groovy 还不支持以这种方式开箱即用的混合(如果有的话)。 但是有一个第 3 方库可以用来模拟这种行为:Injecto。 mixin 可以使用 Groovy 1.6 版本(尚未最终版本)中的 AST-Macros 来定义。
您应该始终检查您正在阅读的文档是来自真正的 groovy 项目还是来自 GroovyJSR 项目(这是一个收集提案的地方)。
另一种方法是使用普通的 MOP 通过修改元类将行为注入到 Groovy 类中。
干杯
I guess what you've seen there is rather a proposal than a feature ;) Groovy does not support mixins out of the box in this way yet (if ever). But there is a 3rd party lib that can be used to emulate such a behavour: Injecto. And mixins can be defined using AST-Macros in the 1.6 version of Groovy (which is not final yet).
You should always check if your're reading the docs from the real groovy project or from the GroovyJSR project (which is rather a place where proposals are collected).
Another way is to use plain-old MOP to inject behaviour into groovy classes by modifying metaClasses.
Cheers
如果这对任何人有帮助,根据上面的 @virtualeyes 评论,我发现
除非您先调用以下内容,否则会失败:
之后,类上的静态方法似乎确实有效(对我来说,使用 Grails 2.2.4)我想这与初始化类或其他东西有关,但我尝试过:
但这不起作用!
In case this helps anyone, Following on from @virtualeyes comment above, I've found that
fails unless you call the following first:
after which, the static method on the class does seem to work (for me, using Grails 2.2.4) I guess it's to do with initialising the class, or something, but I tried:
and that didn't work!
仅供参考:Grails 中现在有“嵌入”域之类的东西,但它有问题。 在这里,您可以在逻辑上将一个域包含为另一个域的一部分,并使其字段全部物理地出现在一个数据库表中。 例如,如果您发现多个表中出现相同的字段子集(例如街道地址/城市/州/邮政编码),则可以定义 StreetAddress 域并将其嵌入。 当前的问题之一是,Grails 除了将其字段嵌入到其他表中之外,仍然会创建一个 street_address 表(除非你耍花招)。 似乎有已提交的补丁正在等待处理。
FYI: There is such a thing as "embedded" domains in Grails now, but it has problems. This is where you can logically include one domain as part of another and have its fields all occur physically in the one DB table. For example, if you find that you have the same subset of fields appearing in multiple tables, like street address/city/state/zip, you could define a StreetAddress domain and embed it. One of the current problems is that Grails will still create a street_address table in addition to embedding its fields in the other tables (unless you play tricks). There are submitted patches pending for this, it seems.
Grails 域对象已经经过大量元编程。
尝试使用常规的 mixin 来代替:
Grails domain objects are already heavily meta-programmed.
Instead of the groovy mixin try:
使用特质!
Traits 是他们取消对 mixins 支持的原因,因为那样更好。 它们基本上是已实现的抽象类。 允许您使用多个并将它们作为部分类进行操作。
试试看!
Use Traits!
Traits are the reason they removed support for mixins, because that are just better. They're basically abstract classes that are implemented. Allowing you to use multiple and operate them as partial classes.
Try it out!