В чем разница между Inject и Provider в JSR-330

Все

Я не знаю, в чем разница между Inject и Provider в JSR-330. Я использую Google Guice, и каждый день использую @Injectи я знаю в JSR-330, он имеет Provider<T>,

Мой вопрос

  1. что значит Provider<T>?
  2. когда может когда пользователь Provider<T>?
  3. какая разница с @Inject?

Заранее спасибо.

1 ответ

Решение

Все уже объяснено в javadoc, я цитирую:

По сравнению с инъекционным T напрямую (неявно используя @Inject только), впрыскивая Provider<T> позволяет:

  1. извлечение нескольких экземпляров.
  2. ленивый или необязательный поиск экземпляра.
  3. ломая круговые зависимости.
  4. абстрагирование области видимости, так что вы можете искать экземпляр в меньшей области из экземпляра в содержащей области.

Пример для № 1:

Здесь вы получите несколько экземпляров Seat от того же провайдера, поэтому он используется в качестве фабрики.

class Car {
    @Inject 
    Car(Provider<Seat> seatProvider) {
        Seat driver = seatProvider.get();
        Seat passenger = seatProvider.get();
        ...
    }
}

Пример для № 2:

Здесь вы используете провайдера, чтобы не создавать непосредственно экземпляр класса MyClassLongToCreate поскольку мы знаем, что это медленная операция, поэтому мы получим ее лениво благодаря get метод только тогда, когда это необходимо.

class MyClass {
    @Inject
    private Provider<MyClassLongToCreate> lazy;
    ...
}

Пример для № 3:

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

class C1 {
    private final C2 c2;
    @Inject
    C1(C2 c2) {
        this.c2 = c2;
        ...
    }
}

class C2 {
    private final C1 c1;
    @Inject
    C2(C1 c1) {
        this.c1 = c1;
        ...
    }
}

Чтобы исправить это, мы используем Provider по крайней мере на одном из конструкторов, чтобы разорвать круговую зависимость следующим образом:

class C1 {
    private final Provider<C2> c2;
    @Inject
    C1(Provider<C2> c2) {
        this.c2 = c2;
        ...
    }
}

Это позволит контейнеру полностью создать экземпляр C1 во-первых (поскольку нам на самом деле не нужно создавать экземпляр C2 ввести поставщика C2), когда контейнер будет готов, он сможет создать экземпляр C2 из этого экземпляра C1,

Пример для № 4:

Здесь у вас есть класс C2 это ограничено сессией, которая зависит от C1 что его область действия ограничена запросом, мы используем провайдера, чтобы мы могли получить экземпляр C1 соответствует текущему запросу, поскольку он будет меняться от одного запроса к другому.

@RequestScoped
public class C1 {
    ...  
}

@SessionScoped
public class C2 {
    @Inject
    private Provider<C1> provider;
    ...
    public void doSomething() {
        // Get the instance corresponding to the current request
        C1 c1 = provider.get();
        ...
    }
}
Другие вопросы по тегам