Guice @Provides 方法与提供程序类
我正在做一个相当大的项目,有很多注射。我们目前使用的是一个类,该类为需要一个的每次注入实现,并且它们大多具有一行方法。Provider
get
每次我需要一个新的提供者时,创建一个新类开始变得很烦人。在我的方法中使用提供程序类有什么好处,反之亦然?@Provides
Module
我正在做一个相当大的项目,有很多注射。我们目前使用的是一个类,该类为需要一个的每次注入实现,并且它们大多具有一行方法。Provider
get
每次我需要一个新的提供者时,创建一个新类开始变得很烦人。在我的方法中使用提供程序类有什么好处,反之亦然?@Provides
Module
据我所知,对于大多数简单情况,它们是完全等效的。
/**
* 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 都允许您注入 和 ,即使键绑定到类或实例也是如此。如果直接获取实例,Guice 会自动调用,如果实例不存在,Guice 会自动创建隐式实例。绑定批注在两种样式中都有效。Foo
Provider<Foo>
get
Provider<Foo>
@Provides的主要优点是紧凑性,特别是与匿名内部提供程序实现相比。但是,请注意,在某些情况下,您可能希望支持提供程序类:
您可以创建自己的长期提供程序实例(可能使用构造函数参数),并将键绑定到这些实例而不是类文本。
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 执行第二次查找。
提供程序易于修饰或包装,如果您希望(例如)在不使用 Guice 作用域或绑定的情况下缓存或记忆实例。
bind(Foo.class).toProvider(new Cache(new FooProvisioner("bar", "baz")));
重要说明:虽然对于 Guice 无法创建的类,这是一个很好的策略,但请记住,Guice 可以以任何方式自动为你的任何 T 创建和注入 a,包括类名、键或实例。无需创建显式提供程序,除非涉及您自己的实际逻辑。Provider<T>
bind
类的实例化方式也有所不同。例如:
public class GumProvider implements Provider<Gum> {
public Gum get() {
return new Gum();
}
}
public class GumModule extends AbstractModule {
protected void configure() {
bind(Gum.class).toProvider(GumProvider.class);
//bind(Gum.class).to(GumballMachine.class);
}
}
public class GumballMachine {
@Inject
private Provider<Gum> gumProvider;
Gum gum;
public Gum dispense() {
return gumProvider.get();
}
}
public class App {
public static void main(String[] args) {
// TODO Auto-generated method stub
Injector injector = Guice.createInjector(new GumModule());
GumballMachine m = injector.getInstance(GumballMachine.class);
System.out.println(m.dispense());
System.out.println(m.dispense());
}
}
这将创建一个每次调用的口香糖实例。然而,如果使用@Provides,相同的口香糖实例将被传递给两个注射器