java Guice 注入空指针
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/13298128/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Guice injection null pointer
提问by user1810567
We try to refactoring a project with Guice. The idea is to bind all the Languageinterface to a concreate object like Frenchor Polish.
我们尝试用 Guice 重构一个项目。这个想法是将所有Language接口绑定到一个 concreate 对象,比如French或Polish。
We have a module for binding:
我们有一个用于绑定的模块:
public class StandardModule extends AbstractModule {
@Override
protected void configure() {
bind(Language.class).to(Polish.class);
}
}
And a classe (AboutDialog.java) that use this injected object :
还有一个使用这个注入对象的类(AboutDialog.java):
@Inject Language language;
public AboutDialog(JFrame parent) {
super(parent, "", true);
this.language=language;
this.setTitle(language.getLanguageInUse().getString("AboutDialog.title"));
this.parent = parent;
try {
jbInit();
} catch (Exception e) {
e.printStackTrace();
}
pack();
}
And we have as result:
结果是:
java.lang.NullPointerException at net.sf.jmoney.gui.AboutDialog.<init>(AboutDialog.java:67)
Line 67 is:
第 67 行是:
this.setTitle(language.getLanguageInUse().getString("AboutDialog.title"));
Our interface is:
我们的界面是:
public interface Language {
public ResourceBundle getLanguageInUse();
}
And the Polish class is:
波兰语课是:
public class Polish implements Language {
private ResourceBundle languageInUse;
public Polish() {
languageInUse = ResourceBundle.getBundle(Constants.LANGUAGE_PL);
}
public ResourceBundle getLanguageInUse() {
return languageInUse;
}
}
We are lost...
我们迷路了...
采纳答案by Daniel Manzke
I assume that your are not creating your AboutDialog
with the help of Guice.
我假设您不是AboutDialog
在 Guice 的帮助下创建的。
What you could do is use injector.injectMembers(this)
where this
is the AboutDialog
.
你可以做的是使用injector.injectMembers(this)
where this
is the AboutDialog
.
The best way would be that the AboutDialog
will be created by Guice, so all members will be injected.
最好的方法是AboutDialog
由 Guice 创建,因此所有成员都将被注入。
回答by Jeff Bowman
You're using "field injection". This will make it hard to use your injected values in a constructor; even if Guice were to create the object (which is not happening now) or you were to use injector.injectMembers(aboutDialog)
, the constructor would run before the injector has a chance to inject the field you want.
您正在使用“现场注入”。这将使在构造函数中使用注入的值变得困难;即使 Guice 要创建对象(现在不会发生)或者您要使用injector.injectMembers(aboutDialog)
,构造函数也会在注入器有机会注入您想要的字段之前运行。
It's a little more tricky to create a class that takes a varying parameter as well as an injected parameter. This leaves you with a few options:
创建一个接受可变参数和注入参数的类有点棘手。这让您有几个选择:
Inject the JFrame. If you know what JFrame you're going to use when the constructor is being created, then just use
bind(JFrame.class).toInstance(myJFrame);
in your Module. Then Guice can create the AboutDialog entirely.Create a Factory manually. That way you can inject
AboutDialog.Factory
and just callcreate
to get yourAboutDialog
. It'll look something like this:public class AboutDialog extends JDialog { /** Injectable factory. */ public static class Factory { @Inject private Language language; public AboutDialog create(JFrame parent) { return new AboutDialog(parent, language); } } // no @Inject parameter; you're calling "new" yourself above! public AboutDialog(JFrame parent, Language language) { super(parent, "", true); this.language = language; // ... other initialization } }
Create a Factory and let Guice wire it up for you via assisted injection.
public class AboutDialog extends JDialog { public interface Factory { public AboutDialog create(JFrame parent); } // you need the @Inject, and also the @Assisted to tell Guice to // use the parameter instead of Guice bindings @Inject public AboutDialog(@Assisted JFrame parent, Language language) { super(parent, "", true); this.language = language; // ... other initialization } } public class StandardModule extends AbstractModule { @Override protected void configure() { bind(Language.class).to(Polish.class); // here every method in AboutDialog.Factory will be implemented // to create the method's return type [AboutDialog] based on // the parameters (like JFrame) and the bindings (like Language) install(new FactoryModuleBuilder().build(AboutDialog.Factory.class)); } }
注入 JFrame。如果您知道在创建构造函数时将使用什么 JFrame,那么只需
bind(JFrame.class).toInstance(myJFrame);
在您的模块中使用即可。然后Guice 可以完全创建AboutDialog。手动创建工厂。这样您就可以注入
AboutDialog.Factory
并调用create
以获取您的AboutDialog
. 它看起来像这样:public class AboutDialog extends JDialog { /** Injectable factory. */ public static class Factory { @Inject private Language language; public AboutDialog create(JFrame parent) { return new AboutDialog(parent, language); } } // no @Inject parameter; you're calling "new" yourself above! public AboutDialog(JFrame parent, Language language) { super(parent, "", true); this.language = language; // ... other initialization } }
创建一个工厂,让 Guice 通过辅助注射为您连接起来。
public class AboutDialog extends JDialog { public interface Factory { public AboutDialog create(JFrame parent); } // you need the @Inject, and also the @Assisted to tell Guice to // use the parameter instead of Guice bindings @Inject public AboutDialog(@Assisted JFrame parent, Language language) { super(parent, "", true); this.language = language; // ... other initialization } } public class StandardModule extends AbstractModule { @Override protected void configure() { bind(Language.class).to(Polish.class); // here every method in AboutDialog.Factory will be implemented // to create the method's return type [AboutDialog] based on // the parameters (like JFrame) and the bindings (like Language) install(new FactoryModuleBuilder().build(AboutDialog.Factory.class)); } }
As noted in the question comments, make sure you're getting your AboutDialog
(or AboutDialog.Factory
via an @Inject
ed constructor/field or from the Injector
itself, or else Guice will not know to inject the parameters.
如问题评论中所述,请确保您正在获取您的AboutDialog
(或AboutDialog.Factory
通过@Inject
ed 构造函数/字段或从其Injector
本身获取,否则 Guice 将不知道注入参数。