Насколько я знаю, они в точности эквивалентны для большинства простых случаев.
/**
* Class-style provider.
* In module: bind(Foo.class).annotatedWith(Quux.class).toProvider(MyProvider.class);
*/
class MyProvider implements Provider<Foo> {
@Inject Dep dep; // All sorts of injection work, including constructor injection.
@Override public Foo get() {
return dep.provisionFoo("bar", "baz");
}
}
/**
* Method-style provider. configure() can be empty, but doesn't have to be.
*/
class MyModule extends AbstractModule {
/** Name doesn't matter. Dep is injected automatically. */
@Provides @Quux public Foo createFoo(Dep dep) {
return dep.provisionFoo("bar", "baz");
}
@Override public void configure() { /* nothing needed in here */ }
}
В любом стиле, Guice позволяет вводить Foo
и Provider<Foo>
, даже если ключ связан с классом или экземпляром. Guice автоматически вызывает get
, если вы получаете экземпляр напрямую и создает неявный Provider<Foo>
, если он не существует. Связывающие аннотации работают в обоих стилях.
Основным преимуществом @Provides является компактность, особенно по сравнению с анонимными внутренними реализациями поставщика. Однако следует отметить, что там может быть несколько случаев, когда вы хотите, чтобы благоприятствовать Provider классы:
Вы можете создавать свои собственные долгоживущие экземпляры провайдера, возможно, с параметрами конструктора, и привязать ключи тех случаях, а не класса литералов.
bind(Foo.class).toProvider(new FooProvisioner("bar", "baz"));
Если вы используете рамки, совместимые с JSR 330 (javax.inject), вы можете легко связать с классами javax.inject.Provider или экземпляров. com.google.inject.Provider расширяет этот интерфейс.
bind(Foo.class).toProvider(SomeProviderThatDoesntKnowAboutGuice.class);
Ваш Провайдер может быть достаточно сложным, чтобы фактор в свой класс. В зависимости от того, как вы структурировали свои тесты, может быть проще протестировать вашего провайдера таким образом.
Провайдеры могут расширять абстрактные классы. Это может быть нелегко или интуитивно, чтобы сделать это с помощью методов @Provides.
Вы можете связать несколько ключей с одним и тем же провайдером напрямую. Каждый метод @Provides создает ровно одну привязку, хотя вы можете связать другие ключи с ключом (здесь @Quux Foo), и пусть Guice сделает второй поиск.
Провайдеров легко украсить или обернуть, если вы хотите (например) кешировать или memoize экземпляры без использования областей или привязок Guice.
bind(Foo.class).toProvider(new Cache(new FooProvisioner("bar", "baz")));
ВАЖНЫ: Хотя это хорошая стратегия для классов, которые Guice не может создавать, иметь в виде, что Guice может автоматически создавать и впрыснуть Provider<T>
для любого T, что вы bind
в любом случае, включая имя класса, ключ или экземпляр. Нет необходимости создавать явный провайдер, если не существует реальной логики вашего собственного участия.