Dependency Injection #
Introduction #
As Wikipedia puts it:
Dependency injection is a technique whereby one object supplies the dependencies of another object.
If class A
requires instances of classes B
and C
, B
and C
are considered
dependencies of A
. When instantiating class A
, you can either supply these dependencies yourself or rely on
something called a dependency container to do this for you. A dependency container holds all the dependencies of your
classes and injects them into your classes when they are required.
The dependency injection pattern is a powerful design pattern that makes for more flexible software design and easier testing.
In Diego, dependency injection is implemented using Google Guice.
💡 You can read more about this design pattern on the Guice Wiki.
Using the dependency container #
You can access the dependency container in one of two ways:
- Use the
@Inject
annotation - Use the
inject()
method from theUsesDependencyService
trait
Using the @Inject
annotation
#
The main way of getting objects from the dependency container is by using the @com.google.Inject
annotation in your classes. A good example of where this is useful is when you want to inject a Service
or Database
into your application:
class MyApplication extends Application {
private final Database db
@Inject
MyApplication(Database db) {
this.db = db
}
void configure(Router router) {
router.get('/', (req, res) -> {
// Use the db object here
})
}
}
You can place the @Inject
annotation on constructors (ideal), methods or (least ideal) fields. All injection sites must be marked as public
.
Using the inject() method #
Another, more direct way, of creating instances of classes with dependencies is by accessing the dependency container directly. To get access to the dependency container, have your class use the
UsesDependencyService
trait, which will give you access to the inject(Class<?>)
method (as seen in the Database chapter).
class MyScheduledJob implements UsesDependecyService {
private Database db = inject(Database)
}
Some classes such as Application
use this trait out of the box, so you don’t need to explicitly use this trait.
Adding modules to the dependency container #
You can add your custom modules to the dependency container. First, you create a Module
(tutorial
here) and tell the dependency container to load it when creating
your application using the app.modules
configuration key.
app.modules = ["modules.MyModule"]
Providers in your module will have access to:
- The root Vertx instance;
- The loaded application settings via the
Settings
singleton; - The configured
ObjectMapper
singleton; and - The configured
BodyHandler
singleton
Further reading #
If you would like to learn more about Guice you can look at the official Guice wiki and Baeldung’s Guide to Google Guice.
Next: Testing