Below is a short & crisp tutorial on Guice and the functionalities offered by it
What is Guice?
Guice is framework in Java to inject dependencies to configure Java Objects. The dependency injection pattern leads to code that is more modular & testable.
Consider an interface BillingService as below:
Consider below implementation of the BillingService Class:
It is easy to see the problems with above solutioning as it would make testing the code impossible!
Let's model the BillingService implementation by including its dependencies in constructor:
It is now possible to send mock Object or FakeCreditCard Object using a custom FakeCreditCardProcessor. But it still has a problem that BillingService's client need to lookup it dependencies , basically you will need to construct dependencies recursively while you need to use a service.
This is where Guice comes for rescue!
Dependency Injection with Guice
To Use Guice for dependency injection in above example we need to do two things:
1. bind all the dependencies in a Java class that implements the Guice Module interface.
A module is a collection of bindings specified using fluent, English-like method calls
2. add @inject annotation on top of the class's constructor which will instruct Guice to use the bindings.
We add @Inject to RealBillingService's constructor, which directs Guice to use it. Guice will inspect the annotated constructor, and lookup values for each parameter.
The Injector can now be used to get an instance of any of the bound classes as below :
With dependency Injection , each object can accept dependency in their constructor ; it's dependency can also accept some dependencies in its
own constructor.So when you build an object, you really need to build an object graph. Injector is basically the graph builder in Guice.
Type Of Bindings in Guice:
1. Linked Bindings
Linked Bindings map a type to its implementation as in the above example. It can link a class to its implementing class or an extending class.It can also be used to chain bindings i.e bind a concrete class to its subclass as below:
In this case, when a TransactionLog is requested, the injector will return a MySqlDatabaseTransactionLog.
2. Binding Annotations
You can have use cases like you have more than 1 bindings for the same type.Let's say you have a PaypalCreditProcessor and GoogleCheckoutProcessor that you need to bind.In such case you can declare a BindingAnnotation as below:
Then, add this Bindingannotation "@paypal" while injecting inside the BillingService Constructor as below:
You then need to bind as below using "annotatedwith":
So you need to do 3 things in essence : 1.Declare a BindingAnnotation with an apt name for the annotation , 2.While Injecting in the constructor add the annotation with the Object, 3.use "annotatedWith" while defining bindings in the module.
Guice also comes with a built-in binding annotation @Named , here you won't need to create a binding annotation.
You need to use Names.named with the "annotatedWith" as below:
3. Instance Bindings
You can also bind an type to a particular instance of that type
Avoid doing it with complex Objects as it will slow down application startup use @Provides instead.
4. @Provides Method
This method is used when you want to bind an instance to a type just like instance binding.
The method must be defined within a module, and it must have an @Provides annotation. The method's return type is the bound type. Whenever the injector needs an instance of that type, it will invoke the method.
In case of Named annotations like @Named("paypal") you can mention Names.named("paypal") with the Object as done previously in the constructor.
Use this as below:
5. JIT Bindings
@ImplementedBy:
It acts as a basic linked binding , but it has lower precedence than the "bind" method declared inside the Guice module.
@ProvidedBy:
@ProvidedBy tells the injector about a Provider class that produces instances
Comments
Post a Comment