3

我的 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 实例。

4

1 回答 1

10

在本教程http://code.google.com/p/google-gin/wiki/GinTutorial的帮助下,您的问题看起来并不那么困难。您应该运行几个步骤来将菜单实例注入视图。

  1. 将@Inject 注解添加到菜单字段。

    public ErrorView implements View {
    
      @Inject
      private Menu menu;
    }
    
    public SearchView implements View {
    
      @Inject
      private Menu menu;
    }
    

    但在这种情况下,菜单字段在 View 对象初始化期间(在构造函数中)将为空。因此,我更喜欢将此字段添加到构造函数参数中。

    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的构造函数中有许多其他参数,它就不起作用,因为它们都需要注入。

  2. 现在我们必须确保 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);
      

在某些示例中,我将菜单字段设置为最终字段并删除它的设置器,但如果您确实需要菜单的可变状态,您可以将其保持不变。

于 2012-05-02T07:15:54.810 回答