Google Guice is a dependency injection library that allows you to construct objects simply by declaring relationships between them. Objects are constructed as they are demanded to construct other objects. You can also implement abstract classes or interfaces with different implementations by configuring Guice, which makes it very useful for running or testing your code.
@Inject
annotates constructors and methods that determine what an object needs to be initialized. There are also a lot of other annotations that determine how Guice works. But simply annotating objects isn't enough; you also have to configure them with Guice bindings.
Here's a really simple example (from one of my applications). I have a MySQLDataTracker
that requires a MysqlConnectionPoolDataSource
:
public class MySQLDataTracker extends ExperimentDataTracker {
@Inject
public MySQLDataTracker(MysqlConnectionPoolDataSource ds) {
....
}
}
Note that MySQLDataTracker
extends ExperimentDataTracker
, an abstract class that can be implemented several ways. In my Guice bindings I declare that
bind(ExperimentDataTracker.class).to(MySQLDataTracker.class);
This declares that whenever I want an ExperimentDataTracker
, a MySQLDataTracker
will be constructed. I also need to make sure that the requisite object for constructing this is available, so I declare a provider:
@Provides @Singleton
MysqlConnectionPoolDataSource getMysqlCPDS() {
return (some thingy I construct...);
}
This says that there should only be a single connection pool data source. It also means that when I try to get an instance of ExperimentDataTracker
, Guice has everything it needs to construct it. If I didn't have the above, it would throw an error.
ExperimentDataTracker tracker = injector.getInstance(ExperimentDataTracker.class);
However, it doesn't stop here. Other things depend on the ExperimentDataTracker
, so it's used in turn to inject other objects. At the top level of my code there is actually only one call to getInstance
, which makes Guice construct pretty much everything. I don't have to write the new
statement anywhere.
I'm a big fan of Guice after seeing how it reduced the need for me to initialize a bunch of objects in order to initialize other objects. Basically I just ask for the object I want, and poof! it appears.