Guice впрыскивает только часть конструктора - PullRequest
12 голосов
/ 06 февраля 2012

Предположим, у меня есть класс Message, подобный следующему. (Это подготовленный класс для простоты.)

public class Message {
  private String text;

  public Message(String text) {
    this.text = text;
  }

  public void send(Person recipient) {
    // I think I should be Guice-injecting the sender.
    MessageSender sender = new EmailBasedMessageSender();
    sender.send(recipient, this.text);
  }
}

Так как у меня есть различные реализации MessageSender, и, возможно, я захочу провести модульное тестирование этой способности отправки, я думаю, что я должен вводить MessageSender в Message метод send(). Но как мне это сделать?

Все примеры Guice, которые я видел и которые, как я понимаю, делают инъекцию в конструктор:

public class Message {
  private String text;
  private MessageSender sender;

  // ??? I don't know what to do here, since the `text` argument shouldn't be injected.
  @Inject
  public Message(String text, MessageSender sender) {
    this.text = text;
    this.sender = sender;
  }

  public void send(Person recipient) {
    this.sender.send(recipient, this.text);
  }
}

public class MessageSenderModule extends AbstractModule {
  @Override 
  protected void configure() {
    bind(MessageSender.class).to(EmailBasedMessageSender.class);
  }
}

Но мой класс Message принимает аргумент text в своем конструкторе, который я не хочу вставлять. Так что я должен делать вместо этого?

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

1 Ответ

19 голосов
/ 06 февраля 2012

Вы можете использовать вспомогательную инъекцию для предоставления текста через фабрику вместе с отправителем сообщения, созданным Guice:

public class Message {
  private String text;
  private MessageSender sender;

  @Inject
  public Message(@Assisted String text, MessageSender sender) {
    this.text = text;
    this.sender = sender;
  }

  public void send(Person recipient) {
    this.sender.send(recipient, this.text);
  }
}

Factory:

public interface MessageFactory{
    Message buildMessage(String text);
}

Модуль:

public class MessageSenderModule extends AbstractModule {
  @Override 
  protected void configure() {
    bind(MessageSender.class).to(EmailBasedMessageSender.class);
    FactoryModuleBuilder factoryModuleBuilder = new FactoryModuleBuilder();
    install(factoryModuleBuilder.build(MessageFactory.class));
  }
}

использование:

@Inject MessageFactory messageFactory;

void test(Recipient recipient){
  Message message = messageFactory.buildMessage("hey there");
  message.send(recipient);
}

Вспомогательный впрыск Wiki

...