Вопрос

Мы оцениваем использование GIN в нашем проекте GWT и получили хорошие результаты при типичном внедрении через аргументы конструктора.У нас возникли трудности с инъекцией на уровне поля.Поля всегда оказываются нулевыми.Есть ли у кого-нибудь хороший пример того, как правильно реализовать внедрение на уровне поля с помощью 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.TestPresenter, который требуется DetailPresenter, внедряется успешно, но HandlerManager, который требуется TestPresenter, всегда имеет значение null.Как видите, внедренный HandlerManager не используется в конструкторе.

Это было полезно?

Решение

Обновите, посмотрев пример кода:

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

Поскольку вы создаете его самостоятельно, предполагается, что вы уже имели дело с какими-либо инъекциями.Удалите этот метод, и он вызовет конструктор по умолчанию (при необходимости внедрит туда), а затем посетит любой другой сайт внедрения.

Еще одна проблема, с которой вы можете столкнуться:существует несколько реализаций HandlerManager, убедитесь, что все ваши ссылки на HandlerManager используют один и тот же пакет.


Оригинальный ответ:

Во время работы конструктора они будут равны нулю, но это имеет смысл — как они могут иметь любое другое значение, если у инжектора еще не было возможности назначить все поля.Подумайте, как это могло бы работать (выраженное здесь как сомнительно законная Java, поскольку поля могут быть не общедоступными):

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

К тому времени, когда поле можно будет назначить, ваш конструктор уже будет запущен.

Если поле имеет значение null при запуске другого метода, убедитесь, что этот метод не запускается. конструктором, но после того, как инъекция завершила свою работу.Другие случаи, когда оно может быть нулевым, будут @Inject аннотированные сеттеры.

Предполагая, что это не один из этих случаев (самый простой способ проверить — установить точку останова и убедиться, что инжектор не находится в стеке вызовов), убедитесь, что поле действительно имеет @Inject, и что он не привязан к нулевому экземпляру.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top