Подтвердить что ты не робот

Как избежать инжектора .createInstance() повсюду при использовании guice?

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

public static void main(String[] args) {
    /*
     * Guice.createInjector() takes your Modules, and returns a new Injector
     * instance. Most applications will call this method exactly once, in their
     * main() method.
     */
    Injector injector = Guice.createInjector(new BillingModule());

    /*
     * Now that we've got the injector, we can build objects.
     */
    RealBillingService billingService = injector.getInstance(RealBillingService.class);
    ...
  }

Но что, если не все объекты, которые мне нужны, могут быть созданы во время запуска? Может быть, я хочу ответить на некоторые взаимодействия с пользователем, когда приложение запущено? Разве мне не нужно держать инжектор где-нибудь (например, как статическую переменную), а затем вызвать инжектор .getInstance(SomeInterface.class), когда мне нужно создать новый объект?

Конечно, распространение запросов на Injector.getInstance() по всему месту кажется нежелательным.

Чем я здесь ошибаюсь?

4b9b3361

Ответ 1

Да, вы в основном должны использовать инжектор, чтобы создать экземпляр для корневого объекта. Остальная часть приложения не должна касаться Guice-Container. Как вы заметили, вам все равно нужно создавать некоторые объекты, когда это необходимо. Для этого существуют разные подходы, каждый из которых подходит для различных потребностей.

Внедрение поставщика Provider - это интерфейс от Guice. Он позволяет запрашивать новый экземпляр объекта. Этот объект будет создан с использованием Guice. Например.

 class MyService{
     private Provider<Transaction> transactionProvider;
     public MainGui(Provider<Transaction> transactionProvider){
         this.transactionProvider = transactionProvider;
     }

     public void actionStarted(){
         Transaction transaction = transactionProvider.get();
     }

Создайте Factory Часто вам нужен какой-то factory. Этот factory использует некоторые внедренные службы и некоторые параметры и создает для вас новый объект. Затем вы используете этот factory для новых экземпляров. Затем вы вводите этот factory и используйте его. Там также можно помочь с AssistedInject -extension

Я думаю, что с этими двумя возможностями вам редко нужно использовать сам Guice-Injector. Однако иногда по-прежнему целесообразно использовать сам инжектор. Затем вы можете ввести Инжектор в компонент.

Ответ 2

Чтобы распространить ответ на опубликованный Gamlor, вам также нужно провести различие между типами объектов, которые вы используете.

Для служб инъекция - это правильное решение, однако не пытайтесь всегда делать инъекционные данные (которые обычно являются листами на вашем графике объектов). Могут быть ситуации, когда это правильное решение, но инъекция Provider<List>, вероятно, не очень хорошая идея. Мой коллега закончил это, он сделал кодовую базу очень запутанной через некоторое время. Мы только что закончили чистку, и теперь модули Guice стали более конкретными.

Ответ 3

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

BillingService billingService = injector.getInstance(BillingService.class);
billingService.respondToUserEvent( event );

Я предполагаю, что это может быть немного абстрактным, но основная идея заключается в том, что вы получаете от Guice свой класс приложений верхнего уровня. Судя по вашему вопросу, я полагаю, что, возможно, BillingService - это не ваш класс верхнего уровня?