我正在从事一个相当大的项目,其中有很多注入(inject)。我们目前正在使用一个实现 Provider
的类,每个注入(inject)都需要一个,它们大多只有一行 get
方法。
每次我需要一个新的提供者时都需要创建一个新类,这开始变得很烦人。在我的 Module
中使用提供程序类而不是 @Provides
方法有什么好处,反之亦然?
最佳答案
据我所知,对于大多数简单的情况,它们是完全等价的。
/**
* 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 都允许您注入(inject) Foo
和 Provider<Foo>
,即使键绑定(bind)到类或实例。 Guice 自动调用 get
如果直接获取实例并创建隐式 Provider<Foo>
如果一个不存在。绑定(bind)注释适用于两种样式。
@Provides 的主要优点是紧凑,尤其是与匿名内部 Provider 实现相比。但是请注意,在某些情况下您可能希望支持 Provider 类:
您可以创建自己的长生命周期 Provider 实例,可能带有构造函数参数,并将键绑定(bind)到这些实例而不是类文字。
bind(Foo.class).toProvider(new FooProvisioner("bar", "baz"));
如果您使用的是与 JSR 330 (javax.inject) 兼容的框架,您可以轻松绑定(bind)到 javax.inject.Provider 类或实例。 com.google.inject.Provider 扩展了该接口(interface)。
bind(Foo.class).toProvider(SomeProviderThatDoesntKnowAboutGuice.class);
您的 Provider 可能足够复杂,可以考虑到它自己的类中。根据您构建测试的方式,以这种方式测试您的 Provider 可能更容易。
提供者可以扩展抽象类。使用@Provides 方法执行此操作可能并不容易或不直观。
您可以将多个 key 直接绑定(bind)到同一个提供者。每个 @Provides 方法只生成一个绑定(bind),尽管您可以将其他键绑定(bind)到键(此处为@Quux Foo)并让 Guice 进行第二次查找。
如果您想(例如)在不使用 Guice 作用域或绑定(bind)的情况下缓存或内存实例,则提供程序很容易装饰或包装。
bind(Foo.class).toProvider(new Cache(new FooProvisioner("bar", "baz")));
重要:虽然这对于 Guice 无法创建的类来说是一个很好的策略,但请记住 Guice 可以自动创建并注入(inject) Provider<T>
对于你 bind
的任何 T以任何方式,包括类名、键或实例。除非涉及您自己的实际逻辑,否则无需创建显式提供程序。
关于java - Guice @Provides 方法与提供者类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28202882/