What is dependency injection?
Instead of initiating the object we are dependent on, we take help of a dependency framework which will push the ready made object to the dependent class during runtime.
In the above picture we are not initializing hotDrink with new hotDrink(), instead we are getting it as a constructor parameter.
Why is it useful?
This is useful to decouple two different code packages and remove direct dependency.
If you have an interface which can have multiple implementations, with the dependency injection framework, you can choose to run which implementation to run at runtime. Suppose you want to isolate and test a particular package, you can provide mock implementations of all other interfaces it is dependent on.
If you have to do the same without DI injection and interfaces, then you need to change code in lot of places, calling mock object at all the places you were calling original object to test.
It is useful when you have dependencies depending on other dependencies and so on.
Implementing with Google Guice:
You should usually initialize the injector where you bootstrap the program.
bind or guice configure() helps you define which implementation of interface to use.
@implementedby annotation can be used instead of configure() and bind.
@implementedby can be used as a default one.
If both guice module(bind) and @implementedby compete for different implementations of same interface, guice module wins.
when you want to select between implementation by giving type as input and also you want to pass input inside.