The @Inject
annotation is applied to injection points - methods,
constructors, or fields that a dependency injection tool like Guice or Dagger
will invoke or populate to construct an object.
Scope annotations (annotations that are themselves annotated with
@ScopeAnnotation
) are used to denote the ‘effective scope’ of an object.
Examples of scope annotations include @Singleton
, @RequestScope
,
@SessionScope
. These annotations can be used either on the declaration of a
type (so that every instantiation of that object will be handled with the
appropriate scope), or on a provider method (to declare that the particular
binding declared by that provider method is subject to that annotation’s scoping
rules):
@Singleton
class ExpensiveGlobalObject {
@Inject ExpensiveGlobalObject(SomeDependencies stuff) {...}
}
class SomeModule extends AbstractModule {
...
@Provides
@Singleton
OtherExpensiveObject provideOtherExpensiveObject() { return new Gold(); }
}
Qualifier annotations (annotations that are themselves annotated with
@Qualifier
or @BindingAnnotation
) are used to distinguish different
instances of the same type of object (the @Red Robot
instead of the @Blue
Robot
). These annotations can be used inside injection points, or on those
provider methods:
class RobotArena {
@Inject RobotArena(@Red Robot redBot, @Blue Robot blueBot) {...}
}
class SomeModule extends AbstractModule {
...
@Provides
@Red
Robot provideRedRobot() { return new Robot("red"); }
}
Notably: there is no method declaration where @Inject
and either a scope or a
qualifier annotation can reasonably coexist. Either the method is an injection
point, and the dependency injection system will ignore the scope or qualifier
annotation, or the method is a provider method, and the @Inject
method
won’t have any effect, as modules are constructed without a dependency injection
container.
class Example {
// Here, @Singleton is ignored. Perhaps the scope should go onto Example, to make dependency
// injection systems treat the Example type as a singleton.
@Inject @Singleton
Example(Robot something) {}
}
class MyModule extends AbstractModule {
...
// The `@Inject` doesn't do anything: Guice will use this method to define a Singleton binding
// for Database. When a Database is constructed by Guice, a DatabaseCredentials will be
// constructed and this method will be invoked, but it isn't invoked until then.
@Provides @Singleton @Inject
Database providesSingletonDatabase(DatabaseCredentials db) { ... }
}
Suppress false positives by adding the suppression annotation @SuppressWarnings("QualifierOrScopeOnInjectMethod")
to the enclosing element.