2

我们正在评估在 GWT 项目中使用 GIN 的情况,并且通过构造函数参数的典型注入取得了良好的结果。我们遇到的困难是现场水平注入。这些字段总是最终为空。有没有人有一个很好的例子来说明如何使用 GIN 正确实现归档级别注入?

更新:

这是一些类似于我们的示例代码:

public class MVP implements EntryPoint {

  public static final HandlerManager EVENT_BUS = new HandlerManager(null);
  private final MVPInjector _injector = GWT.create(MVPInjector.class);

  public void onModuleLoad() {
    // set up layout for module
    RootLayoutPanel.get().add(mainPanel);

    // initialize presenters
    ListPresenter listPresenter = _injector.listPresenter();
    DetailPresenter detailPresenter = _injector.detailPresenter();

    listPresenter.go(listContainer);
    detailPresenter.go(detailContainer);

    // simulate data coming in from RPC call
    EVENT_BUS.fireEvent(new DataReadyEvent(getData()));
  }
}

public class ListPresenter {

  private final HandlerManager _eventBus;
  private final Map<String, Fruit> _myRecords = new HashMap<String, Fruit>();
  private final Display _view;

  @Inject
  public ListPresenter(Display argView, HandlerManager argEventBus) {
    _eventBus = argEventBus;
    _view = argView;
  }

  public void go(HasWidgets argContainer) {
    argContainer.clear();
    argContainer.add(_view.asWidget());
  }

  public interface Display {
    public Widget asWidget();

    public void clear();

    public SingleSelectionModel<ViewProxy> getSelectionModel();

    public void setData(List<ViewProxy> argData);
  }
}

public class DetailPresenter {

  private final HandlerManager _eventBus;
  private final Display _view;
  private Fruit _myRecord;

  @Inject
  private ImagePresenterFactory _imagePresenterFactory;

  @Inject
  private TestPresenter _testPresenter;

  @Inject
  public DetailPresenter(Display argView, HandlerManager argEventBus) {
    _view = argView;
    _eventBus = argEventBus;
  }

  public void go(HasWidgets argContainer) {
    argContainer.clear();
    argContainer.add(_view.asWidget());

    if (_testPresenter != null) {
      _testPresenter.go();
    }
  }

  public interface Display {
    public Widget asWidget();

    public HasText getDescriptionControl();

    public HasClickHandlers getImageControl();

    public HasText getNameControl();

    public HasClickHandlers getSaveControl();

    public void setEnabledControls(boolean argEnabled);
  }
}

public class TestPresenter {

  @Inject
  HandlerManager _eventBus;

  public TestPresenter() {}

  public void go() {
    if (_eventBus != null) {
      _eventBus.toString();
    }
    else {
      // event bus was not injected
    }
  }
}

@GinModules(MVPModule.class)
public interface MVPInjector extends Ginjector {

  DetailPresenter detailPresenter();

  ListPresenter listPresenter();

}

public class MVPModule extends AbstractGinModule {

  @Provides
  @Singleton
  public HandlerManager getEventBus() {
    return MVP.EVENT_BUS;
  }

  @Provides
  public TestPresenter getTestPresenter() {
    return new TestPresenter();
  }

  @Override
  protected void configure() {
    bind(ListPresenter.Display.class).to(ListView.class);
    bind(DetailPresenter.Display.class).to(DetailView.class);
    bind(ImagePresenter.Display.class).to(ImagePopup.class);
    install(new GinFactoryModuleBuilder().build(ImagePresenterFactory.class));
  }

  public interface ImagePresenterFactory {
    public ImagePresenter createImagePresenter(ImageResource argImage);
  }

}

在上面的代码中,我已经删除了大部分不涉及 GIN 的代码。DetailPresenter 所需的 TestPresenter 注入成功,但 TestPresenter 所需的 HandlerManager 始终为 null。可以看到,注入的 HandlerManager 并没有在构造函数中使用。

4

1 回答 1

1

更新,查看示例代码:

@Provides
public TestPresenter getTestPresenter() {
  return new TestPresenter();
}

因为您是自己创建的,所以它假定您已经处理了任何注入。删除此方法,它将调用默认构造函数(如果需要,在此处注入),然后访问任何其他注入站点。

您可能会遇到另一个问题:有几个 HandlerManager 实现,请确保您对 HandlerManager 的所有引用都使用相同的包。


原答案:

当构造函数运行时它们将为空,但这是有道理的——当注入器还没有机会分配所有字段时,它们怎么可能是任何其他值。考虑这将如何运行(此处表示为可疑的合法 java,因为字段可能不公开):

InstanceToInject instance = new InstanceToInject(...);
instance.field = provideFieldValue();

当该字段甚至可以被分配时,您的构造函数已经运行。

如果在运行另一个方法时该字段为 null,请确保该方法不是由构造函数运行,而是在注入完成其工作之后运行。其他可能为 null 的情况将是@Inject带注释的 setter。

假设不是这些情况(最简单的检查方法是设置断点,并确保注入器不在调用堆栈中),请确保该字段确实有一个@Inject,并且它没有绑定到空实例。

于 2012-02-27T02:31:52.233 回答