Faker for Grails给出了变量未定义的错误 [英] Faker for Grails gives variable not defined error
问题描述
我有一个使用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。因此,如果您声明 那么为什么我会喋喋不休呢?依赖注入由Spring完成 - 你正在注入Spring bean。有多种方法可以做到这一点,但Grails中的默认方式是使用autoinject-by-name。因此,对于在 您添加了一个局部变量。局部变量没有什么特别的地方,Spring也没有看到它们,它们也不是依赖注入的候选对象。在 ,Groovy编译器会添加一个不太感兴趣的 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. 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 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 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 and the Groovy compiler will add a 这篇关于Faker for Grails给出了变量未定义的错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋! 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)。
ApplicationContext
中注册的任何bean以及像 BootStrap
,集成测试等特殊类,Spring会扫描方法寻找二传手。它剥离set并降低下一个字母,这就是setter的属性名称。如果在 ApplicationContext
中有一个具有该名称的bean,Spring将调用该setter,传递具有该名称的bean,并且如果类型同步,则类将拥有引用该bean。
init
闭包之前将声明移至类作用域,例如
class BootStrap {
def fakerService
def init = {
...
}
}
getFakerService
方法,也是Spring将会看到的 setFakerService
方法。它将确定其属性名称为fakerService,请参阅具有该名称的bean,并调用setter。这一切都发生在Grails调用 init
闭包之前,因此此时该值将是非空的 FakerService
热切地等待您的来电。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
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).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.init
closure, e.g.class BootStrap {
def fakerService
def init = {
...
}
}
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.