Faker for Grails给出了变量未定义的错误 [英] Faker for Grails gives variable not defined error

查看:113
本文介绍了Faker for Grails给出了变量未定义的错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个使用spring-security-core配置的Grails 2.4.4应用程序。我想使用 faker插件在BootStrap中生成假用户。但是,当我在BootStrap中实例化bean fakerService并尝试使用它即ie。 fakerService.firstname(),出现错误:

  ERROR上下文.GrailsContextLoaderListener  - 初始化应用程序时出错:无法在null对象上调用方法firstName()
消息:无法在null对象上调用firstName()方法

我只是Grails的初学者。我在做依赖注入错误吗?



http://pasteboard.co/rvbihRU.png

解决方案

是的,您是:)

背景。当您在Groovy类中添加一个类作用域变量(一个字段)而没有明确的作用域修饰符(例如public,private,protected)时,它就像类和方法一样默认为public。但它被认为是JavaBean意义上的属性,所以Groovy编译器会根据名称为您创建一个getter和setter。因此,如果您声明 def foo 字符串栏(指定类型无关紧要)得到 Object getFoo() void setFoo(Object), String getBar() code>和 void setBar(String)方法(你应该用一个反编译器反编译一个POGO类并亲自查看 - 这非常酷 - 我推荐<一个href =http://jd.benow.ca/ =nofollow> JD-GUI ,但是使用你喜欢的任何东西)。如果你已经声明了其中任何一个,Groovy就会跳过那一个,而不会覆盖你的。这很酷,因为你可以像简单的公共字段那样对待变量,但是可以随时添加getter和/或setter逻辑,而不会影响调用客户端(Groovy或Java,因为Java类一直会一直调用getter和setter ,而当你读或写一个属性时,Groovy会为你调用getter和setter)。

那么为什么我会喋喋不休呢?依赖注入由Spring完成 - 你正在注入Spring bean。有多种方法可以做到这一点,但Grails中的默认方式是使用autoinject-by-name。因此,对于在 ApplicationContext 中注册的任何bean以及像 BootStrap ,集成测试等特殊类,Spring会扫描方法寻找二传手。它剥离set并降低下一个字母,这就是setter的属性名称。如果在 ApplicationContext 中有一个具有该名称的bean,Spring将调用该setter,传递具有该名称的bean,并且如果类型同步,则类将拥有引用该bean。



您添加了一个局部变量。局部变量没有什么特别的地方,Spring也没有看到它们,它们也不是依赖注入的候选对象。在 init 闭包之前将声明移至类作用域,例如

  class BootStrap {

def fakerService

def init = {
...
}
}

,Groovy编译器会添加一个不太感兴趣的 getFakerService 方法,也是Spring将会看到的 setFakerService 方法。它将确定其属性名称为fakerService,请参阅具有该名称的bean,并调用setter。这一切都发生在Grails调用 init 闭包之前,因此此时该值将是非空的 FakerService 热切地等待您的来电。


I have a Grails 2.4.4 application configured with spring-security-core. I want to generate fake users in the BootStrap using the faker plugin. However when I instantiate the bean fakerService in BootStrap and try using it ie. fakerService.firstname(), I get an error :

ERROR context.GrailsContextLoaderListener  - Error initializing the application: Cannot invoke method firstName() on null object
Message: Cannot invoke method firstName() on null object

I'm just a beginner in Grails. Am I doing the Dependency Injection wrong?

http://pasteboard.co/rvbihRU.png

解决方案

Yes you are :)

A little background. When you add a class-scope variable (a field) in a Groovy class without an explicit scope modifier (e.g. public, private, protected) it defaults to public just like classes and methods. But it is considered a property in the JavaBean sense, so the Groovy compiler creates a getter and a setter for you based on the name. So if you declare def foo and String bar (it doesn't matter whether you specify the type) you'll get Object getFoo(), void setFoo(Object), String getBar(), and void setBar(String) methods (you should decompile a POGO class with a decompiler and see this for yourself - it's pretty cool stuff - I recommend JD-GUI, but use whatever you prefer). If you had declared any of them already Groovy would skip that one and not overwrite yours. This is cool because you can treat the variable like a simple public field, but at any time add getter and/or setter logic and not affect calling clients (Groovy or Java, since the Java classes would have been calling the getter and setter all along, and Groovy calls the getter and setter for you when you read or write a property).

So why am I babbling on about this? Dependency injection is done by Spring - you're injecting Spring beans. There are various ways to do this, but the default in Grails is to use autoinject-by-name. So for any bean registered in the ApplicationContext and special classes like BootStrap, integration tests, etc., Spring scans the methods looking for setters. It strips off "set" and lowercases the next letter, and that's the "property" name of the setter. If there's a bean with that name in the ApplicationContext, Spring will call that setter, passing the bean with that name, and if the types are in sync, your class will have a reference to that bean.

You added a local variable. Nothing special happens to local variables, and Spring doesn't see them, and they're not candidates for dependency injection. Move the declaration to class scope, before the init closure, e.g.

class BootStrap {

   def fakerService

   def init = {
      ...
   }
}

and the Groovy compiler will add a getFakerService method that isn't of much interest, but also a setFakerService method that Spring will see. It will determine that its property name is "fakerService", see that there is a bean with that name, and call the setter. This all happens before Grails calls the init closure, so at that point the value will be a non-null FakerService eagerly awaiting your calls.

这篇关于Faker for Grails给出了变量未定义的错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆