Home > Enterprise >  How does Guice inject classes without an @Inject-annotated constructor?
How does Guice inject classes without an @Inject-annotated constructor?

Time:02-24

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 and javax.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.

  • Related