【问题标题】:Injecting an instance using Gin/Guice使用 Gin/Guice 注入实例
【发布时间】:2012-05-01 15:41:54
【问题描述】:

我的 GWT 项目中通常有这种代码模式:

Menu errorMenu = new Menu(user, userController, -1);
Menu  searchMenu = new Menu(user, userController, 0);

errorView.setMenu(errorMenu);
searchView.setMenu(searchMenu);

如何使用 Gin/Guice 在 ErrorView 和其他“视图”中注入 Menu 实例:

public ErrorView implements View {
 // Inject menu instance here
 private Menu menu;
}

这样,我就不用手动创建和设置对象了吗?

对于Menu 类,我如何注入“user”和“userController”对象,这样我就不必在每次实例化时将它传递给每个Menu 实例。

【问题讨论】:

  • 由于我的应用程序中只有一个 User 和 UserController 实例,所以有没有办法也注入它

标签: gwt dependency-injection guice gwt-gin


【解决方案1】:

在本教程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),另一个注入 搜索查看到 - 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);
      

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

【讨论】:

  • 在“public class DefaultErrorMenu extends Menu”中是否也注入了user和userController?
  • 在我的控制器类中,我通常有这种模式:XyzController(final Application application, final XyxModel model)
  • user 和 userController 对象将在以下情况下被注入:1)它们具有不带参数的默认构造函数,2)它们具有 @Inject 注释并且它们在您的 GinModule 类中进行了描述:bind(User.class).somethingelse .....
  • 我不明白这是什么模式?无论如何,您应该在 XyzController 类的构造函数中添加 @Inject 注解。
  • 顺便说一句,我也修改了这段代码来注入我的应用程序模型,但是当访问使用 @Inject 注入的模型并使用 bind(UserModel.class).in(Singleton.class) 绑定时,它会抛出 NullPointerException );
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-01-12
  • 2011-05-13
相关资源
最近更新 更多