Guiceを使用してプロジェクトのリファクタリングを試みます。アイデアは、すべてのLanguageインターフェイスをFrenchまたはPolishのようなconcreateオブジェクトにバインドすることです。
バインディング用のモジュールがあります。
public class StandardModule extends AbstractModule {
@Override
protected void configure() {
bind(Language.class).to(Polish.class);
}
}
そして、この注入されたオブジェクトを使用するクラス(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;
}
}
迷っちゃった...
Guiceの助けを借りてAboutDialog
を作成していないと思います。
できることは、injector.injectMembers(this)
を使用することです。ここでthis
はAboutDialog
です。
最善の方法は、AboutDialog
がGuiceによって作成されるため、すべてのメンバーが注入されることです。
「フィールドインジェクション」を使用しています。これにより、注入された値をコンストラクターで使用することが難しくなります。 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に アシストインジェクション を介して接続させます。
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
(またはAboutDialog.Factory
を@Inject
edコンストラクタ/フィールド経由またはInjector
自体から取得していることを確認してください。 Guiceはパラメータを挿入することを知りません。