2016-11-02 12 views
2

всеКакая разница между Inject и Поставщиком в JSR-330

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

Мой вопрос

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

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

ответ

5

Все уже объяснено в 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 что itslef контекстного на запрос, мы используем поставщик, чтобы позволить нам получить экземпляр 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(); 
     ... 
    } 
} 
+1

примеры очень ясно, спасибо Nicolas – diligent

+0

# 2 - медленное это не единственная причина, вы можете также иметь потребность в объекте впрыскивается будет создан, когда на самом деле нужно, а не в начальный момент времени впрыска. –

+0

@ ThorbjørnRavnAndersen, если на # 2 вы имеете в виду «Пример для №2», это всего лишь пример, чтобы показать идею больше ничего. То, что вы описали, уже упоминалось в моем ответе, это «необязательный поиск» –