我的GWT项目中通常有这种代码模式:
Menu errorMenu = new Menu(user, userController, -1);
Menu searchMenu = new Menu(user, userController, 0);
errorView.setMenu(errorMenu);
searchView.setMenu(searchMenu);
如何使用Gin / Guice在Menu
和其他“视图”中注入ErrorView
个实例:
public ErrorView implements View {
// Inject menu instance here
private Menu menu;
}
这样,我不必手动创建和设置对象?
同样对于Menu
类,如何注入“user”和“userController”对象,这样我每次实例化时都不必在每个Menu实例上传递它。
答案 0 :(得分:10)
借助本教程http://code.google.com/p/google-gin/wiki/GinTutorial,您的问题看起来并不那么困难。要将菜单实例注入View,应该运行几个步骤。
将@Inject注释添加到菜单字段。
public ErrorView implements View {
@Inject
private Menu menu;
}
public SearchView implements View {
@Inject
private Menu menu;
}
但是在这种情况下,在View对象初始化期间(在构造函数中)菜单字段将为null。因此,我更喜欢将此字段添加到构造函数参数中。
public ErrorView implements View {
private final Menu menu;
@Inject
public ErrorView(Menu menu) {
this.menu = menu;
}
}
public SearchView implements View {
private final Menu menu;
@Inject
public SearchView(Menu menu) {
this.menu = menu;
}
}
当然,如果你在ErrorView的构造函数中有许多其他参数,它将无法工作,因为所有这些参数都需要注入。
现在我们必须确保GIN知道ErrorView中的菜单字段应该是
注入new Menu(user, userController, -1)
和另一个注入
SearchView至 - new Menu(user, userController, 0)
。我们做得到
通过以下几种方式:
在您的菜单字段中添加注释@Named("searchMenu")
和@Named("errorMenu")
。
public ErrorView implements View {
@Inject
@Named("errorMenu")
private Menu menu;
}
或
public ErrorView implements View {
private final Menu menu;
@Inject
public ErrorView(@Named("errorMenu") Menu menu) {
this.menu = menu;
}
}
在您的GIN模块中,您应该提供此注释的定义。
public class ApplicationGinModule extends AbstractGinModule {
protected void configure() {
bind(Menu.class).annotatedWith(Names.named("errorMenu")).to(DefaultErrorMenu.class);
bind(Menu.class).annotatedWith(Names.named("searchMenu")).to(DefaultSearchMenu.class);
//assume that User and UserController classes have default constructors
//otherwise you should provide correct injection depending on your business-logic
bind(User.class).in(Singleton.class);
bind(UserController.class).in(Singleton.class);
}
}
public class DefaultErrorMenu extends Menu {
@Inject
public DefaultErrorMenu(User user, UserController userController) {
super(user, userController, -1);
}
}
public class DefaultSearchMenu extends Menu {
@Inject
public DefaultSearchMenu(User user, UserController userController) {
super(user, userController, 0);
}
}
在菜单字段中创建自己的注释@SearchMenu
和@ErrorMenu
,并在模块中定义它们。
注释示例:
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD, ElementType.PARAMETER, ElementType.METHOD, ElementType.TYPE})
@BindingAnnotation
public @interface ErrorMenu {
}
用法:
public ErrorView implements View {
@Inject
@ErrorMenu
private Menu menu;
}
或
public ErrorView implements View {
private final Menu menu;
@Inject
public ErrorView(@ErrorMenu Menu menu) {
this.menu = menu;
}
}
然后按照你如何定义@Named(“ErrorMenu”)的方式定义注释:
bind(Menu.class).annotatedWith(ErrorMenu.class).to(DefaultErrorMenu.class);
在某些示例中,我将菜单字段设为final并删除setter,但如果您确实需要菜单的可变状态,则可以保持不变。