1

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

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

我的用例的完整代码源可在bitbucket 存储库中找到

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

定义 guice 绑定的GuiceServletContextListener :

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 被正确注入,但标签标题字符串始终为空。任何想法?

4

6 回答 6

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

}

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

于 2012-01-05T14:46:46.600 回答
1

解决方案是使用构造函数而不是字段注入在 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 + ")"));
    }
}

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

由于这篇文章,解决方案被注入了我。

于 2011-12-04T13:46:21.683 回答
0

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

@Inject void foo(Injector i){
 System.out.println("injected");
}
于 2011-12-04T13:11:02.813 回答
0

为什么不只是这样?

bind(String.class)
.annotatedWith(Names.named("title"))
.toInstance("This is a guicy Vaadin Application");
于 2011-12-04T12:05:25.227 回答
0

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

于 2011-12-04T17:25:36.890 回答
0

标题是在应用程序类中注入的吗?

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

于 2011-12-04T12:34:25.623 回答