Suppose you have the the following Java classes:
class Foo {}
class Bar {
Foo foo;
public Bar(Foo foo) {
this.foo = foo;
}
}
Now you need an instance of Bar
. Here is how you do that in an ordinary Java application:
Foo foo = new Foo();
Bar bar = new Bar(foo);
The problem with above code is you hard code the dependency management into your application and it makes it hard to refactor the code when you want to replace the current Foo
implementation with another SuperFoo
implementation. And if your Foo
is a very complicated object and is expensive to construct but you want to unit test Bar
then you also introduce unnecessary complexity into unit test.
Now here is how Genie and other JSR330 DI solutions handle the case. First add javax.inject.Inject
annotation to your Bar
class:
class Bar {
private Foo foo;
@Inject
public Bar(Foo foo) {
this.foo = foo;
}
}
And now Genie way to get your Bar
instance:
Genie genie = Genie.create();
Bar bar = genie.get(Bar.class);
An important thing is the application developer doesn't need to touch Foo
, the dependency of Bar
. Genie manage to instantiate the instance of Foo
when it need it to construct the Bar
instance. This abstraction leaves the space for application developer to centralize the configuration of dependency management and they doesn't need to get distracted from that when programming the business logic. It also makes it flexible to replace implementations if needed. See Type binding for more details.
In the above Bar
code we have implemented one of three kind of injections: Constructor injection. Genie also support the other two injection types:
Field injection:
class Bar {
@Inject
private Foo foo
}
Method injection:
class Bar {
private Foo foo;
@Inject
public void foo(Foo foo) {
this.foo = foo;
}
}
Here are some points about the three injection types:
- Field/Method injection will be ignored when Constructor injection presented
- Field injection is not very unit test friendly because it force you to create new module to inject your mock dependencies.
- Method injection is not preferred when you favor immutability or you want to protect your object internal state
Whatever injection type you are using in your application, use it consistently.
Now that you have some basic idea of dependency injection with Genie, you can move to the next chapter to see how to use Genie to bind your interface to a concrete implementation.