2012-05-16 20 views
3

我正在使用Google Guice作为IOC容器的Java Swing应用程序。我直接注入组件,但这让Guice在EDT之外创建组件使用Guice注入Swing组件的最佳实践?

应用程序看起来有点像这样:

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

如果你想使用'loader',你应该实现com.google.inject.Provider。请看例子在http://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; 
} 

或者相反,如果你只需要一个实例每个组件可以直接将实例绑定到该类型:

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); 
}