我们尝试用Guice重构项目。我们的想法是将所有 Language 接口绑定到一个混合对象,如法语或 Polish 。
我们有一个绑定模块:
public class StandardModule extends AbstractModule {
@Override
protected void configure() {
bind(Language.class).to(Polish.class);
}
}
使用此注入对象的classe(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();
}
我们有结果:
java.lang.NullPointerException at net.sf.jmoney.gui.AboutDialog.<init>(AboutDialog.java:67)
第67行是:
this.setTitle(language.getLanguageInUse().getString("AboutDialog.title"));
我们的界面是:
public interface Language {
public ResourceBundle getLanguageInUse();
}
波兰语课程是:
public class Polish implements Language {
private ResourceBundle languageInUse;
public Polish() {
languageInUse = ResourceBundle.getBundle(Constants.LANGUAGE_PL);
}
public ResourceBundle getLanguageInUse() {
return languageInUse;
}
}
我们迷路了...
答案 0 :(得分:10)
你正在使用“现场注射”。这将使得在构造函数中使用注入的值变得困难;即使Guice要创建对象(现在没有发生)或者你要使用injector.injectMembers(aboutDialog)
,构造函数也会在注入器有机会注入你想要的字段之前运行。
创建一个采用变量参数和注入参数的类有点棘手。这为您提供了一些选择:
注入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通过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));
}
}
如问题评论中所述,请确保您通过AboutDialog
ed构造函数/字段或AboutDialog.Factory
本身获取@Inject
(或Injector
,否则Guice不会知道注入参数。
答案 1 :(得分:8)
我假设您没有在Guice的帮助下创建AboutDialog
。
您可以使用injector.injectMembers(this)
,其中this
是AboutDialog
。
最好的方法是由Guice创建AboutDialog
,这样就会注入所有成员。