我有一个非常简单的 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。有什么想法吗?
答案 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注释或公共字段。