Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Guice: implications of field injection

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!

like image 246
IAmYourFaja Avatar asked Apr 13 '12 14:04

IAmYourFaja


People also ask

How does field injection work in Guice?

Field injection in the context of DI means that we annotate the fields of a class with the @Inject annotation, which tells Guice to inject the dependency directly into the class. We can also then remove them from the constructor, since we won't be calling the constructor at all.

Why field based injection is not recommended?

The reasons why field injection is frowned upon are as follows: You cannot create immutable objects, as you can with constructor injection. Your classes have tight coupling with your DI container and cannot be used outside of it. Your classes cannot be instantiated (for example in unit tests) without reflection.

Which is better constructor or field injection?

Constructor Injection is always the first choice when it comes about Dependency Injection because of its reliable and strict nature. Field Injection can also be used in the scenarios where Constructor Injection is absolutely not possible (and Circular Dependencies have to be avoided even as a work around).

What is @inject annotation in Guice?

@Target(value={METHOD,CONSTRUCTOR,FIELD}) @Retention(value=RUNTIME) @Documented public @interface Inject. Annotates members of your implementation class (constructors, methods and fields) into which the Injector should inject values. The Injector fulfills injection requests for: Every instance it constructs.


1 Answers

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.

like image 86
Ryan Nelson Avatar answered Oct 04 '22 10:10

Ryan Nelson