Что произойдет, если вы передадите Injector в качестве аргумента в методе @Provides - PullRequest
0 голосов
/ 21 декабря 2018

Я видел несколько случаев использования в проекте, в котором я работаю следующим образом (я публикую сущность кода, чтобы его было легче читать):

public static void main(Strings[] args) {
    Injector i = Guice.createInjector(new MyModule());
    i.getInstance(Foo.class);
}

class Foo {}

class MyModule extends AbstractModule {
    @Provides
    public Foo getFoo(Injector injector) {
        return new Foo();
    }
}

Когда я пытался напечатать injector.toString() в модуле, я думаю, что Guice каким-то образом связал Инжектор с самим экземпляром i.

Как, например,

public static void main(Strings[] args) {
    Injector i = Guice.createInjector(new MyModule());
    Injector j = i.getInstance(Injector.class);
    if (i == j) {
        // true
    }
}
....

Так что в этом случае кто-то может пролить свет на то, какGuice получает экземпляр Injector в методе getFoo(injector)?Спасибо!

1 Ответ

0 голосов
/ 03 января 2019

Инжектор внедряется в ваш график, и Guice предоставит аргументы для @Provides методов.Тем не менее, вам нужно вводить инъектор только в очень редких случаях, и нет необходимости запрашивать инжектор, если вы его не используете.


@Provides
public Foo getFoo(Dep1 dep1, Dep2 dep2) {
    return new Foo(dep1, dep2);
}

Это предполагает, что Guice может создатьэкземпляры Dep1 и Dep2 (через конструкторы, привязки или @Provides методы), и это примерно эквивалентно тому, если вы аннотировали конструктор в Foo.Guice будет вводить экземпляры Dep1 и Dep2 при вызове конструктора Foo, а Guice будет предоставлять экземпляры при вызове вашего @Provides Foo getFoo метода, описанного выше.

@Inject public Foo(Dep1 dep1, Dep2 dep2) { /* ... */ }

Как и в документации для класса Injector, который вы связали ( последние документы доступны здесь ):

Содержит несколько привязок по умолчанию:

  • Этот Injector сам экземпляр
  • A Provider<T> для каждой привязки типа T
  • Logger для вводимого класса
  • Stage, в котором был создан Инжектор

Следовательно, вы можете поместить Dep1, Dep2, Provider, Provider, Injector или Provider<Injector> в свои @Provides аргументы метода или @Inject аргументы конструктора (или @Inject поля и т. Д.).Внутренне поддержка Injector происходит в InjectorShell.java как особый случай, поскольку родительские и дочерние Injectors будут возвращать различные экземпляры Injector в качестве исключения из правил Guice относительно родителей и детей с одинаковыми привязками.


Зачем вам вводить инжектор? Для чтения и тестирования обычно лучше ввести нужную вам зависимость (например, Dep1) или ее поставщика (например, Provider<Dep1>).).Вам нужно будет только ввести Инжектор, если вам нужно передать его в какой-либо другой объект, например, в устаревший Сервисный Локатор, который вы приспособили для использования вашего Guice Injector, или если вам нужно использовать Инжектор отражательно через SPI Guice или для получения экземпляра на основе объекта Class .Они редки и вряд ли будут необходимы в большинстве ваших классов или @Provides методов.

/** Exceptions, generics, and casting omitted for readability. */
@Provides SomeInterface getSomeInterface(
    MyAppPreferences preferences,
    Injector injector) {
  Class<?> clazz = Class.forName(preferences.getSomeInterfaceImplName());
  return injector.getInstance(clazz);
}

См. Также: Доступ к инжектору Guice в его модуле?

...