3

IOC コンテナーとして Google Guice を使用して Java Swing アプリケーションに取り組んでいます。コンポーネントを直接注入していますが、これにより、Guice はEDT の外部にコンポーネントを作成できます。

アプリケーションは次のようになります。

private Panel1 panel1;
private Panel2 panel2;

@Inject
public class Application(Panel1 panel1, Panel2 panel2) {
    this.panel1 = panel1;
    this.panel2 = panel2;
}

herehereの質問を見て、コンポーネントを直接注入するのではなく、ローダーを注入するという結論に達しました。

private PanelLoader1 loader1;
private PanelLoader2 loader2;

private Panel1 panel1;
private Panel2 panel2;

@Inject
public class Application(PanelLoader1 loader1, PanelLoader2 loader2) {
    this.loader1 = loader1;
    this.loader2 = loader2;

    loader1.load();
    loader2.load();

    this.panel1 = loader1.get();
    this.panel2 = loader2.get();
}

public class PanelLoader {
    private Panel panel;
    public void load() {
        SwingUtilities.invokeLater(new Runnable() {

            @Override
            public void run() {
                panel = new Panel();
            }
        });
    }
    public Panel get() {
        return panel;
    }
}

これは正しいです?それを行うためのベストプラクティスはありますか?

4

1 に答える 1

4

「ローダー」を使用する場合は、実装する必要がありますcom.google.inject.Providerhttp://code.google.com/p/google-guice/wiki/InjectingProvidersの例を見てください。

プロバイダー自体を注入する必要はありません。プロバイダーによって作成されたオブジェクトを注入するようにモジュールを構成できます。

public class PanelModule extends AbstractModule {

@Override
protected void configure() {
    bind(Panel1.class).toProvider(Panel1Provider.class);
}

private static class Panel1Provider implements Provider<Panel1> {

    private Panel1 panel1;

    @Override
    public Panel1 get() {
        try {
            EventQueue.invokeAndWait(new Runnable() {
                @Override
                public void run() {
                    panel1 = new Panel1();
                }
            });
        } catch (InvocationTargetException e) {
            throw new RuntimeException(e); // should not happen
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
    }
    return panel1;
}

または、コンポーネントごとに 1 つのインスタンスのみが必要な場合は、インスタンスを型に直接バインドできます。

public class PanelModule extends AbstractModule {

Panel1 panel1;
Panel2 panel2;

@Override
protected void configure() {

    try {
        EventQueue.invokeAndWait(new Runnable() {
            @Override
            public void run() {
                panel1 = new Panel1();
                panel2 = new Panel2();
            }
        });
    } catch (InvocationTargetException e) {
        throw new RuntimeException(e); // should not happen
    } catch (InterruptedException e) {
        Thread.currentThread().interrupt();
    }

    bind(Panel1.class).toInstance(panel1);
    bind(Panel2.class).toInstance(panel2);
}
于 2012-05-18T21:07:34.500 に答える