结合@Provides 和@Inject

Combining @Provides and @Inject

我最近发现一些代码在同一方法上同时使用了 @Provides@Inject 注释。此方法有两个非原始参数和一个非 void return 类型。

我想知道同时使用这两个是否有意义。据我所知 gather/speculate,似乎 @Inject 用于使用 Guice 构造方法依赖项,而 @Provides 用于绑定 return 类型。任何想法将不胜感激。

不,您绝不会在同一方法上看到 @Provides and @Inject

@Inject 构造函数、方法和字段有意义:

  • 在构造函数上,标记DI框架应该调用的构造函数。该框架提供所有参数值。这通常称为构造函数注入
  • 在字段上,表示DI框架应该从外部设置字段。框架提供字段值。这通常被称为字段注入
  • 在方法上,表示构建DI框架后,应该exactly调用一次方法。框架提供参数值。 return 值没有意义,通常是 void。这通常被称为方法注入

例如:

public class YourInjectableClass {

  // Guice will use this constructor...
  @Inject public YourInjectableClass(YourDep dep) { /* ... */ }
  // ...instead of this one
  public YourInjectableClass(YourDep dep, YourOtherDep otherDep) { /* ... */ }

  // Guice will populate this field after construction.
  @Inject YourField yourField;

  @Inject public void register(Registry registry) {
    // Guice will create or get a Registry and call this method after
    // construction. It sometimes makes sense for this to be protected
    // or package-private so this class's consumers aren't tempted
    // to call it themselves.
  }
}

@Provides has a much narrower purpose: When used in Guice modules, @Provides goes on methods and indicates that Guice should call the method whenever it needs an instance of the method's possibly-parameterized type (and inheriting the binding annotations or qualifiers from the method itself). Dagger has a similar @Provides annotation,因为 @Provides 未在 JSR-330 依赖项注入标准中定义。

对于 Guice 和 Dagger,框架将在调用方法时提供 @Provides 方法的参数,而不使用 @Inject@Inject 的语义无论如何都没有意义,因为即使以与上面的方法注入类似的方式提供参数,框架也可能重复调用 @Provides 方法,但 @Inject 方法只被调用一次。

public class YourModule extends AbstractModule {
  @Override public void configure() {)  // still needed for AbstractModule

  // Guice will call this whenever it needs a
  // @SomeBindingAnnotation YourInstance. Because you list a YourDep as a
  // parameter, Guice will get and pass in a YourDep.
  @Provides @SomeBindingAnnotation YourInstance create(YourDep dep) {
    return YourInstanceFactory.create(dep);
  }
}

因此,您几乎不应该在同一个文件中看到这些注释,更不用说在同一个方法上了。唯一的例外是,如果您遵循制作本身可注入的模块的可疑做法(可能是从一个注入器获取注入模块以配置不同的注入器),即使这样您也不会在相同的方法上看到它们: @Inject 方法被调用一次以存储依赖项,并且 @Provides 方法应在需要新实例时调用。