Guice – a lightweight DI framework alternative to Spring

What is Guice?

To quote from the Guice official page

“Guice alleviates the need for factories and the use of new in your Java code. Think of Guice’s @Inject as the new new. Guice embraces Java’s type safe nature, especially when it comes to features introduced in Java 5 such as generics and annotations. You might think of Guice as filling in missing features for core Java. Ideally, the language itself would provide most of the same features, but until such a language comes along, we have Guice”

If you’ve used Spring or other DI frameworks you’re probably familiar to the above ideas. I’ll present in this article how to get started with Guice in a non-web application. I’ll detail the web side in a future article.

Is it better than Spring?

Well, this is one of those talks that could last forever. Like EJB vs Spring, Struts vs JSF and so on. It’s a matter of choice. I can say one thing though: if you need just  DI in your application go for Guice. It’s very lightweight, it’s type safe and it’s faster than Spring.

Using Guice for a non-web application

Suppose you have an application and the class that contains the main method its called Application. When using Guice the approach is a little changed. Besides starting the application you’ll also want a way to trigger the dependency injection. In order to to this you must have an “entry-point” that “manually” triggers the creation of the graph of objects that will get injected and only after that starts the actual application logic. We’ll call the class responsible for these 2 things the Bootstrap class. We also need to create a Module by extending the AbstractModule class. Quoting from the Java Doc of the Module interface:

A module contributes configuration information, typically interface bindings, which will be used to create an Injector. A Guice-based application is ultimately composed of little more than a set of Modules and some bootstrapping code.

Let’s see the code:

The Bootstrap class:

package com.insidecoding.guice;
import com.google.inject.Guice;

import com.google.inject.Injector;
/**
 * Bootstrap class that creates the root object that triggers the graph of
 * objects creation and injection
 */
public class Bootstrap {
public static void main(String[] args) {
 Injector injector = Guice.createInjector(new MyModule());
 IApplication app = injector.getInstance(IApplication.class);
 app.start();
 }
}

The IApplication interface:

package com.insidecoding.guice;
public interface IApplication {
 /**
 * Starts the current application
 */
 void start();
}

The Application class:

package com.insidecoding.guice;

import com.google.inject.Inject;

public class Application implements IApplication {
@Inject
 private IPrintingService ip;
public void start() {
 ip.print("Hello from guice");
 }
}

Suppose the logic of your application is as follows: use the IPrintingService to print a String and the printing service will use a ICachingService to cache that String. The implementations of these services will be injected using Guice in the Appplication, respective the ICachingService implementation class.

The IPrintingService interface:

package com.insidecoding.guice;
import com.google.inject.ImplementedBy;

@ImplementedBy(PrintingService.class)
public interface IPrintingService {
/**
 * Prints a string
 * @param s
 */
 void print(String s);
}

The PrintingService class:

package com.insidecoding.guice;

import javax.inject.Inject;

public class PrintingService implements IPrintingService {

	@Inject
	private ICachingService cs;

	@Override
	public void print(String s) {
		System.out.println(s);
		cs.cacheIt(s);
	}

}

The ICachingService:

package com.insidecoding.guice;

import com.google.inject.ImplementedBy;

@ImplementedBy(CachingService.class)
public interface ICachingService {

	/**
	 * Caches a String
	 * @param s
	 */
	void cacheIt(String s);
}

The CachingService class:

package com.insidecoding.guice;

public class CachingService implements ICachingService {

	@Override
	public void cacheIt(String s) {
		System.out.println("Caching: " + s);
	}

}

The MyModule class:

package com.insidecoding.guice;

import com.google.inject.AbstractModule;

public class MyModule extends AbstractModule {

       @Override
       protected void configure() {
          bind(IApplication.class).to(Application.class);
       }
}

The code is pretty simple and straightforward. In order to make this code work, you need to add just the following JARs from the Guice distribution:

  • aopalliance.jar
  • guice-3.0.jar
  • javax.inject.jar

If you take a look closer on the above code you’ll see a small different as far as injection is concerned: the Application class uses the com.google.inject.Inject annotation and the PritingService class uses the javax.inject.Inject annotation. This is because Guice 3.0 is compatible with JSR-330. Mixing JSR-330 and Guice annotations though is discouraged so stick with Guice @Inject for now.

Types of injection

Guice has 3 types of injection:

  • field injection
  • constructor injection
  • method injection
We’ve seen the field injection type in action in the above example. In order to use constructor injection we can modify the PrintingService class to look like this:
package com.insidecoding.guice;

import javax.inject.Inject;

public class PrintingService implements IPrintingService {

	private ICachingService cs;

        @Inject
        public PrintingService(ICachingService cachingService) {
             this.cs = cachingService;
        }

	@Override
	public void print(String s) {
		System.out.println(s);
		cs.cacheIt(s);
	}

}
Note that when using field injection Guice will call the no-arg constructor in order to instantiate objects.
Method injection can be used to inject the parameters. The Guice injector will resolve all dependencies before invoking the method. Injected method can have any number of parameters and the method name has no impact on the injection. Method injection looks as follows:
       @Inject
       public void printMe(IPrintingService ps) {
            ps.print("Printing with Guice method injection");
       }

@ImplementedBy vs bind()

You can notice in the above code that there are 2 ways of declaring bindings between interfaces and implementations:

  • annotate the interface with @ImplementedBy
  • use the bind() method in a Module to specify the actual implementation: see the MyModule.configure() method.
For simple cases and interfaces with just one implementation you can go with the @ImplemenedBy approach, but if you need more control over your bindings or if you deal with multiple implementations definitely use the bind() method.
One important thing to notice is that Guice returns a new instance by default each time it supplies a value. You can switch to singletons using the following code:
bind(ICachingService).to(CachingService).in(Scopes.SINGLETON)
This is just a high level presentation of Guice. You can do a lot more with it and I hope I’ve opened you appetite to discover its capabilities. If you need a lightweight framework for DI, Guice beats Spring all the way.

Please continue reading about using Guice for Web applications.

Recommendations:

About these ads

3 thoughts on “Guice – a lightweight DI framework alternative to Spring

  1. Pingback: Using Google Guice in Web Applications « Inside Coding

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s