Guice


Here is the idea:

You have a class A, which depends on class B and class C.
First step, you want to create interface iB for class B and interface iC for class C, why? won't you rather depend on an interface than an concrete class? This will give a flexibility to use whatever classes you like to use, as long as they implement the interface. For example, B is concrete class for credit card processing, when you do the test, you don't want to call B to do a real credit card processing, right? Ok, so are we good to depend on interface?

Second step, in the run time, which concrete class to use? Guice provides a simple way, called Module, what Module does is binding interface with concrete class. So you could have many Modules, for example, in Module1, you bind iB to class B1, and iC to C1, while in Module2, you could bind iB to class B2, and iC to C2. In runtime, you could decide to use which Module as you like.

Ok, all these are just theories, now let's dive into the bolts and nolts.

Class A have 2 dependencies in iB and iC, in its constructor, you need add an annotation, @Inject, this signal Guice that we want to do Dependency Injection.

In the codes where you want to use class A, you don't need call A's constructor, instead, you use Guice injector

Injector injector = Guice.createInjector(new Module1());
Class A = injector.getInstance(A.class);

That's it.
Let's calm down to understand what's we have just done, it's a lot.

1. We create a Class A instance without calling its constructor.
2. We have binded its 2 dependencies into class A. not just interfaces, but real concrete classes: B1 and C1.

Now you see, A doesn't even know anything about B1 and C1, they are completely decoupled. Their only glue is interface iB and iC. And Guice injector makes it super easy to bind them together in run time. aHa....

Also, you Module1 is also decoupled from Class A, if A doesn't have the annotation, Module1 will just leave it alone.