Guice: implications of field injection

IAmYourFaja picture IAmYourFaja · Apr 13, 2012 · Viewed 15.7k times · Source

My understanding of Guice is that:

  • Constructor-level injection (@Inject public class Widget(Dep one, Dep two)) implies that Guice will always inject that constructor every time it is invoked through an Injector; and
  • Method-level injection (@Inject public void setDepOne(Dep one)) implies that Guice will always inject that method whenever it is called, so long as the Widget object was created using the Guice Injector

Are these two assumptions correct? If not, please clarify!

So what I'm hung up on is: what are the implications of field-level injection?

@Inject private Dep one;

Does this mean that Guice will always inject the property when the object is created through the Guice injector? In that case I would imagine it conflicts with constructor-level injection.

For instance, does the following cause a conflict/error:

public class Widget {
    @Inject private Dep one;

    private Dep two;

    // Dep one already injected as a field!
    @Inject public Widget(Dep one, Dep two) {
        // ...
    }
}

Thanks in advance!

Answer

Ryan Nelson picture Ryan Nelson · Apr 15, 2012

Guice will always inject all fields, methods, and any single constructor annotated with @Inject. Keep in mind the constructor always gets injected first, so your annotated field will actually overwrite that injection. Take this modified example:

class Widget {
    @Inject
    private Dep one;

    @Inject
    public Widget(Dep one) {
        this.one = one;
        System.out.println(one);
    }

    public void printDependency() {
        System.out.println(one);
    }
}

class Dep {}

public class MyMain {
    public static void main(String[] args) {
        Injector i = Guice.createInjector();
        i.getInstance(Widget.class).printDependency();

    }
}

When run, this will produce something like this:

com.example.Dep@63238bd2
com.example.Dep@69198891

Clearly two different objects. The first line is the constructor; the second is the field injection.

I have not often found a use for field injection, except to reduce verbosity when writing Guice code samples. In production code it's unwise because it makes code difficult to test.