I was looking for a lightweight dependency injection framework to use with Groovy and decided try out Google Guice. In this entry I am exploring version 2.0 without AOP.
This is just a quick overview of Guice and there is probably quite a bit more I haven’t discovered yet. I need to give credit to the guy over at dev.eek.be who has written up a great introductory Guice tutorial.
Creating concrete objects
Guice can implicitly create known concrete objects.
import com.google.inject.* class Greeter { String greet() { 'Hello' } } Injector injector = Guice.createInjector() Greeter greeter = injector.getInstance(Greeter.class) println greeter.greet() // Prints 'Hello'
Specifying a default implementation
Guice allows you to specify the default implementation of an interface using the @ImplementedBy annotation.
import com.google.inject.* @ImplementedBy(AussieGreeter.class) interface Greeter { String greet() } class AussieGreeter implements Greeter { String greet() { 'Gudday' } } class FrenchGreeter implements Greeter { String greet() { 'Bonjour' } } Injector injector = Guice.createInjector() Greeter greeter = injector.getInstance(Greeter.class) println greeter.greet() // Prints 'Gudday'
Field injection
We can inject the default implementation of an interface into a class using the @ImplementedBy and the @Inject annotations.
import com.google.inject.* @ImplementedBy(AussieGreeter.class) interface Greeter { String greet() } class AussieGreeter implements Greeter { String greet() { 'Gudday' } } class FriendlyClock { @Inject private Greeter greeter String time() { greeter.greet() + ', the time is ' + new Date().format('h:mma') } } Injector injector = Guice.createInjector() FriendlyClock clock = injector.getInstance(FriendlyClock.class) println clock.time() // Prints something similar to 'Gudday, the time is 12:34PM'
Constructor injection
We can inject via the constructor by moving the @Inject annotation to the constructor method.
import com.google.inject.* @ImplementedBy(AussieGreeter.class) interface Greeter { String greet() } class AussieGreeter implements Greeter { String greet() { 'Gudday' } } class FriendlyClock { private Greeter greeter @Inject def FriendlyClock(Greeter greeter) { this.greeter = greeter } String time() { greeter.greet() + ', the time is ' + new Date().format('h:mma') } } Injector injector = Guice.createInjector() FriendlyClock clock = injector.getInstance(FriendlyClock.class) println clock.time() // Prints something similar to 'Gudday, the time is 12:34PM'
Method injection
We move the @Inject annotation to a method for method injection.
import com.google.inject.* @ImplementedBy(AussieGreeter.class) interface Greeter { String greet() } class AussieGreeter implements Greeter { String greet() { 'Gudday' } } class FriendlyClock { private Greeter greeter @Inject def setGreeter(Greeter greeter) { this.greeter = greeter } String time() { greeter.greet() + ', the time is ' + new Date().format('h:mma') } } Injector injector = Guice.createInjector() FriendlyClock clock = injector.getInstance(FriendlyClock.class) println clock.time() // Prints something similar to 'Gudday, the time is 12:34PM'
Specifying the dependencies using a Module
When you want more dynamic control over which objects are injected we can use a Guice Module to map object interfaces to concrete objects. Here we remove the @ImplementedBy annotation and add a GreeterModule instead.
import com.google.inject.* interface Greeter { String greet() } class AussieGreeter implements Greeter { String greet() { 'Gudday' } } class FrenchGreeter implements Greeter { String greet() { 'Bonjour' } } class FriendlyClock { @Inject private Greeter greeter String time() { greeter.greet() + ', the time is ' + new Date().format('h:mma') } } class GreeterModule implements Module { void configure(Binder binder) { binder.bind(Greeter.class).to(FrenchGreeter.class) } } Injector injector = Guice.createInjector(new GreeterModule()) FriendlyClock clock = injector.getInstance(FriendlyClock.class) println clock.time() // Prints something similar to 'Bonjour, the time is 12:34PM'
Singleton via annotation
An object can be marked as a singleton by using Guice’s @Singleton annotation. Note that the Guice @Singleton annotation conflicts with Groovy’s built-in @Singleton annotation, so we need to use the full path of the annotation class.
First, an example of non-singleton behaviour:
import com.google.inject.* class Greeter { String greeting } injector = Guice.createInjector() greeter = injector.getInstance(Greeter.class) greeter.greeting = 'Gudday' println greeter.greeting greeter = injector.getInstance(Greeter.class) println greeter.greeting
This prints
Gudday null
Now we add the @com.google.inject.Singleton annotation
import com.google.inject.* @com.google.inject.Singleton class Greeter { String greeting } injector = Guice.createInjector() greeter = injector.getInstance(Greeter.class) greeter.greeting = 'Gudday' println greeter.greeting greeter = injector.getInstance(Greeter.class) println greeter.greeting
This prints
Gudday Gudday
Singleton via Module
Singletons can also be specified within a Guice Module.
import com.google.inject.* interface Greeter { void changeGreeting(greeting) String greet(name) } class AussieGreeter implements Greeter { private String greeting = 'Hi'; void changeGreeting(greeting) { this.greeting = greeting } String greet(name) { greeting + ', ' + name } } class GreeterModule implements Module { void configure(Binder binder) { binder.bind(Greeter.class).to(AussieGreeter.class).in(Scopes.SINGLETON) } } injector = Guice.createInjector(new GreeterModule()) greeter = injector.getInstance(Greeter.class) greeter.changeGreeting 'Howdy' println greeter.greet('Groovy') greeter = injector.getInstance(Greeter.class) println greeter.greet('Groovy')
Which prints
Howdy, Groovy Howdy, Groovy
It is retaining the set value and is a singleton.

3 Comments
Thanks for the credits
Nice introduction for Groovy.
Are you planning to use Guice in your next projects?
No problem Wim. Yes, planning to use Guice. It looks like a nice lightweight annotation based DI framwork.
Comment posted to the groovy mailing list about this entry from Brian Schlining:
Only thing I might add is to mention the use of the @Named annotation. It’s one way to bind the same interface or class to different implementations. Here’s a contrived example that injects different JPA EntityManagerFactories :
class FooDaoFactory {
def entityManagerFactory;
@Inject
public FooDaoFactory(@Named(“persist-unit-foo”) EntityManagerFactory entityManagerFactory) {
this.entityManagerFactory = entityManagerFactory;
}
}
class BarDaoFactory {
def entityManagerFactory;
@Inject
public BarDaoFactory(@Named(“persist-unit-bar”) EntityManagerFactory entityManagerFactory) {
this.entityManagerFactory = entityManagerFactory;
}
}
binder.bind(EntityManagerFactory.class).annotatedWith(Names.named(“persist-unit-foo”)).toInstance(Persistence.createEntityManagerFactory(“fooUnit”));
binder.bind(EntityManagerFactory.class).annotatedWith(Names.named(“persist-unit-bar”)).toInstance(Persistence.createEntityManagerFactory(“barUnit”));
def injector = Guice.createInjector()
def foo = injector.getInstance(FooDaoFactory.class);
def bar = injector.getInstance(BarDaoFactory.class);