Vaadin Window组件未完全注入Guice

时间:2011-12-04 11:48:47

标签: guice vaadin guice-servlet

我有一个非常简单的 Vaadin 应用程序。我想使用 Guice 注入我的 Vaadin 应用的主窗口。

我的问题是注入了我的主窗口,但是没有处理这个主窗口组件中的 @Inject 指令。

我的使用cas的完整代码源可在a bitbucket repo

上找到

Vaadin 应用程序类:

public class MyVaadinApplication extends Application {

    protected final Provider<MainWindow> mainWindowProvider;

    @Inject
    @Named("title")
    protected String title;

    @Inject
    public MyVaadinApplication(Provider<MainWindow> mainWindowProvider) {
        this.mainWindowProvider = mainWindowProvider;
    }

    @Override
    public void init() {
        System.out.println("MyVaadinApplication:: found value <"+title+"> for injected title");
        setMainWindow(this.mainWindowProvider.get());
    }
}

MainWindow 类:

public class MainWindow extends Window {

    @Inject
    @Named("title")
    protected String title;
    @Inject
    @Named("label")
    protected String label;
    private static int globalCounter = 0;
    private int localCounter;

    public MainWindow(String caption, ComponentContainer content) {
        super(caption, content);
        initUI();
    }

    public MainWindow(String caption) {
        super(caption);
        initUI();
    }

    public MainWindow() {
        super();
        initUI();
    }

    private void initUI() {
        localCounter = globalCounter;
        globalCounter++;
        this.setCaption(title);
        this.addComponent(new Button(label+" ("+localCounter+")"));
    }
}

GuiceServletContextListener ,其中定义了guice绑定:

public class GuicyServletConfig extends GuiceServletContextListener {

    @Override
    protected Injector getInjector() {

        ServletModule module = new ServletModule() {

            @Override
            protected void configureServlets() {
                serve("/*").with(GuiceApplicationServlet.class);

                bind(Application.class).to(MyVaadinApplication.class).in(ServletScopes.SESSION);
                bind(MainWindow.class).in(ServletScopes.SESSION);
                bindConstant().annotatedWith(Names.named("title")).to("This is a guicy Vaadin Application");
                bindConstant().annotatedWith(Names.named("label")).to("Guice me!");
            }
        };

        Injector injector = Guice.createInjector(module);

        return injector;
    }
}

正确注入MainWindow会发生什么,但标签 title 字符串始终为null。有什么想法吗?

6 个答案:

答案 0 :(得分:1)

解决方案是使用构造函数而不是 field injection 注入需要在MainWindow类中注入的任何内容。请参阅hg repo上的标签stackoverflow-working-with-constructor-injection。

源代码示例

public class MainWindow extends Window {

    protected String title;
    protected String label;
    protected LabelCaption labelCaption;
    private static int globalCounter = 0;
    private int localCounter;

    @Inject
    public MainWindow(@Named("title") String title, @Named("label") String label, LabelCaption labelCaption) {
        super();
        this.title = title;
        this.label = label;
        this.labelCaption = labelCaption;
        initUI();
    }

    private void initUI() {
        localCounter = globalCounter;
        globalCounter++;
        this.setCaption(title);
        String labelFromLabelCaption = "labelCaption is null";
        if (labelCaption != null) {
            labelFromLabelCaption = labelCaption.getCaption();
        }
        this.addComponent(new Button(label + "/" + labelFromLabelCaption + "/(" + localCounter + ")"));
    }
}

不知道为什么字段注入在这种情况下不起作用。

由于this post,解决方案注入给我。

答案 1 :(得分:1)

您还应该考虑以下内容:

public class MainWindow {
  @Inject
  public MainWindow(Injector injector) { 
    this.injector = injector;
  }

  @Override 
  protected void attach() {
     super.attach(); // must call!!!

     this.title = injector.getInstance(something);
     ...

     // set up listeners, etc, here
  }

  @Override
  protected void detach() {
    // disconnect listeners, remove child components
    super.detach();
  }

}

通过这样做,您可以最小化Application实例的大小;在某些环境中,它在存储时被序列化。推迟构建子组件直到它们真正需要(并且对附加的侦听器做同样的事情)可以提供很多帮助。关于这一主题的Vaadin论坛上有更多的消息。

答案 2 :(得分:0)

为什么不是这样的呢?

bind(String.class)
.annotatedWith(Names.named("title"))
.toInstance("This is a guicy Vaadin Application");

答案 3 :(得分:0)

标题中是否注入了标题?

您的问题可能只涉及命名注释吗?尝试在窗口中注入一个bean来仔细检查......

答案 4 :(得分:0)

看起来像是使用提供程序来获取实际实例。您是否尝试过直接注入MainWindow ? 还可以通过添加

来测试实际注入是否发生
@Inject void foo(Injector i){
 System.out.println("injected");
}

答案 5 :(得分:0)

我建议你为标签和标题创建一个setter。 然后在它们上定义@Inject。两者都受到保护我在这种情况下不知道guice行为,但我所有的工作示例都使用带注释的setter注释或公共字段。