【问题标题】:Grails getSomething(int i) method doesn't compileGrails getSomething(int i) 方法无法编译
【发布时间】:2010-09-28 13:51:36
【问题描述】:

谁能告诉我为什么这个 Grails 域类不会编译(在运行时)?

class Person {
    String name

    String getSomething(int i) {
    }
}

当我使用grails run-app 运行时出现此错误:

2008-12-27 15:26:33.955::WARN:  Failed startup of context org.mortbay.jetty.webapp.WebAppContext@187e184{/asrs2,C:\Steve\asrs2/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.NullPointerException
        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.NullPointerException
        at java.lang.Class.isAssignableFrom(Native Method)
        ... 13 more

如果我将方法getSomething 更改为doSomething,那么它可以工作。 getSomething(int i) 是否以某种方式被视为 bean 方法?

跟进:这是一个Grails bug,将在 1.2 中修复。

【问题讨论】:

  • 语句后面不应该加分号吗:"String name;" ?

标签: spring grails groovy


【解决方案1】:

嗯,你有两个问题:

  1. Grails 中的域类尝试确保每个属性在启动期间都有一个 getter 和 setter。它通过查找所有 getter 并确保存在适当的 setter 来做到这一点。所以,如果你有一个 getSomething(),你必须有一个 setSomething(def something),即使类中没有属性“something”。实际上,通过创建 getSomething() 函数,您暗示存在这样一个属性,并且您也必须创建一个 setSomething()。

  2. Getter 不接受参数。你的可以。现在我意识到你写它时并没有认为这是一个“吸气剂”,但你对它的命名使它成为一个。

最好的选择?不要使用“get”或“set”或“is”前缀,除非你真的在制作一个可以获取和设置的完整属性。我也会避免在域类中“查找”,因为它有自己的一组生成方法。

【讨论】:

  • 应该有一个注释,你可以添加一个注释来标记一个以 'get' 开头的方法不是一个 getter/setter 对。
  • 不是通过注解,但是你可以通过“transients”静态属性做到这一点
  • 听起来 Grails 不兼容 Java,因为 getSomething(int) 在 Java 中完全有效。
  • 首先,Grails 不是语言,而是框架(Groovy 是语言)。任何使用约定的框架都会有一些无效的东西。现在,Groovy 是否 100% Java 兼容,也不是,但至少不兼容,没有人说 Groovy 与 Java 相同......他们说它更好:)
【解决方案2】:

一些笔记...

  • 如果您提供了一个 setter,您就不必同时提供一个 getter。反之亦然。您真正要做的是覆盖 Groovy 为您附加的默认访问器方法。如果您愿意,您可以覆盖其中一个而不是另一个。
  • 如果您在域类上创建以“find”开头的方法没有问题,因为动态查找器方法实际上是静态方法添加(并且它们都以“findBy*”开头)。
  • 瞬态解决方案不起作用。将“某物”设为瞬态值无助于您使用错误参数签名的吸气剂这一事实。动态键入返回值时也是如此。
  • 这不是 Groovy 的问题,而是 Grails 的问题。

我认为解决方案是将您的方法名称从 getSomething 更改为 findSomething 或任何您想要的不违反约定的名称。以下工作正常:

class Person {
    String name

    String findSomething(int i) {
    }
}

【讨论】:

    【解决方案3】:

    不要将方法定义为具有返回类型,而是尝试使用def

    class Person {
        String name
    
        def getSomething(int i) {
            // foo
        }
    }
    

    另一种解决方案可能是将something 定义为瞬态(假设您实际上没有名为“某物”的属性):

    class Person {
        String name
    
        static transients = ['something']
    
        String getSomething(int i) {
            // foo
        }
    }
    

    【讨论】:

      【解决方案4】:

      在我回答问题之前,让我告诉你我的环境:
      Grails 1.0.4
      Java 1.6.0_10-beta
      Groovy 1.6-RC-1
      在 Windows Vista 计算机上

      在 grails 中,在运行时为域类中的所有字段添加了动态 get 方法。对于问题中提到的 Person 类,将在运行时添加一个 getName() 方法,这将允许人们在不定义它的情况下使用它。现在问题在于 getSomething(int i) 是你的类中没有一个名为 String something 的字段。如果您尝试添加一个名为 getName(int i) 的方法,它会毫无问题地工作,或者如果您添加一个字段 String 的东西 那么 getSomething() 方法就可以工作了。

      我希望这能暂时解决问题...我会继续寻找并尽快发布有关确切工作的更新。

      【讨论】:

        【解决方案5】:

        我已经得出结论,这是 Grails 的一个错误。我创建了GRAILS-3760,它已在 Grails 1.1.2 中修复。

        【讨论】:

          猜你喜欢
          • 2020-06-14
          • 1970-01-01
          • 2019-02-15
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-04-28
          相关资源
          最近更新 更多