Guice is a Java framework that aims to simplify the application of the Dependency Injection pattern to minimize coupling between modules.
Dependency Injection
As we discussed in a previous post, Dependency Injection (DI) is a way of providing dependencies to clients, rather than having clients explicitly bootstrapping their dependencies by themselves.
That’s one way to achieve Dependency Inversion Principle (DIP), which states:
Instead of depending on implementations, prefer to depend on abstractions.
When applying DI, we need a way to inject (a.k.a. wire, or bind) dependencies into clients that need them. It sure is possible to do it manually when instantiating the client class, or we could pull a framework to help us with the task while also bringing additional benefits, like life-cycle management.
Regarding Java, there is a variety of frameworks, each of those comes with pros and cons, for example, Weld, Spring, Guice, etc.
In this post, we’ll be using Guice.
Google Guice
Google Guice is a framework meant to reduce the boilerplate that comes with DI, it does so by providing a container to where we can map abstractions into implementations. After having established this mapping, the dependencies will be automatically injected into proper clients when requested.
The mapping in Guice is achieved by the implementation of com.google.inject.Module
, which is normally done by inheriting from the
abstract base class com.google.inject.AbstractModule
.
Afterwards, we need to override the configure
method and rely on a fluent API by calling bind
and to
methods, which define the mapping between the abstraction (parameter of bind
) and implementation (parameter of to
).
Then, we can inject the dependencies by annotating your dependencies with com.google.inject.Inject
.
Finally, we need to obtain a com.google.inject.Injector
from our previously defined module, so we are now able to retrieve the client with the
getInstance
method and its dependencies shall then be injected.
Example
The example is part of a Java application that sends log information about its operation. To simplify the inclusion of Guice in our project, we’re going to use Maven as a build tool.
In the pom.xml
, add the following artifact to get Guice at version 4.0 in the dependencies section:
<dependency>
<groupId>com.google.inject</groupId>
<artifactId>guice</artifactId>
<version>4.0</version>
</dependency>
Let’s then create the interface LogSender
to represent the behaviour: “send the log to some medium”:
This service will be used by Exchanger
class, which has a reference to LogSender
and the injection will be done by its constructor annotated with @Inject
:
The implementation StdoutLogSender
will simply send the log to the console:
Now, we need to tell Guice how to bind LogSender
to StdoutLogSender
, and we will do it in the LoggingModule
:
Finally, in the main class Application
, we will create an Injector
and pass our LoggingModule
to its constructor. Therefore, we will able to get an instance of Exchanger
, which will have its dependency on LogSender
bound:
Conclusion
We’ve discussed the basics of how to get started with Google Guice to automate DI tasks in Java applications. We wrote a simple application to exemplify how to define the mapping between abstractions and implementations and how to inject them in our clients.
References
[1] https://medium.com/@varago.rafael/managing-coupling-with-dependency- injection-46157eb1dc4d.
[2] https://www.martinfowler.com/articles/injection.html
[3] https://github.com/google/guice
Originally published at https://medium.com/@rvarago