I'm trying to understand how DI is used in our codebase (Kotlin). We are using google guice for dependency injection.
Here is a sample class:
class ServiceClass @Inject construct(
private val depA: DepA,
private val depB: DepB
) { ........ }
In Module class:
@Provides
fun provideDepA(): DepA {
//constructs DepA object and returns it
}
DepB class:
class DepB { .... }
As far as I know for the variables annotated with @Inject
, Google Guice will look to resolve those dependencies using module class. So it makes sense how DepA
object is injected.
But what about DepB
? How are we able to inject DepB without specifying it anywhere?
CodePudding user response:
Guice bindings that are not declared in modules are known as Just-in-time Bindings, and by default Guice is willing to call constructors that take zero arguments:
Guice Wiki: JustInTimeBindings
Guice can create bindings for concrete types by using the type's injectable constructor. Guice considers a constructor injectable if:
- (recommended) The constructor is explicitly annotated with @Inject (both
com.google.inject.Inject
andjavax.inject.Inject
are supported).- or, the constructor takes zero arguments, and
- the constructor is non-private and defined in a non-private class (Guice supports private constructor only when it is defined in a private class, however, private constructors are not recommended because they can be slow in Guice due to the cost of reflection).
- the injector has not opted in to require explicit @Inject constructor, see explicit @Inject constructors section below.
If you haven't required explicit bindings and you have a public no-arg constructor, Guice will call it as if you had marked it with @Inject
. This is in contrast to Dagger, which will only call @Inject
-annotated constructors:
Dagger Dev Guide
If your class has
@Inject
-annotated fields but no@Inject
-annotated constructor, Dagger will inject those fields if requested, but will not create new instances. Add a no-argument constructor with the@Inject
annotation to indicate that Dagger may create instances as well....
Classes that lack
@Inject
annotations cannot be constructed by Dagger.
In both Guice and Dagger you can construct the objects yourself in @Provides
methods, and in Guice you can also use a Module to explicitly bind to a constructor with arguments and without an @Inject
constructor.