On a high level, Guice and Spring JavaConfig bring many of the same capabilities to the table. They both provide annotation-based dependency injection, they both boast simple APIs, and they both get you quickly up and running with an IoC container.
Spring JavaConfig mainly brings a new type of ApplicationContext into the picture, namely JavaConfigApplicationContext, along with various support infrastructure including new annotations such as @Bean, @Configuration, etc. Otherwise, it's still the same familiar Spring.
Guice follows a different albeit similar model, introducing non-Spring infrastructure including annotations, support classes, etc. The only scent of Spring hovers around the SpringIntegration class.
Comparing the two side-by-side exhibits their similarities as dependency injection frameworks, and exposes their differences as Spring-integrable modules. This comparison includes a single interface and implementation, called Greeter and DefaultGreeter, which define and realize a simple function called getGreeting() which returns the obligatory "Hello World!".
public class DefaultGreeter implements Greeter {
public String getGreeting() {
return "Hello World!";
}
}
The Guice Module, an analog to a Spring context configuration, simply binds the Greeter interface to the only implementation of DefaultGreeter.
import com.earldouglas.guicespringjc.DefaultGreeter;
import com.earldouglas.guicespringjc.Greeter;
import com.google.inject.AbstractModule;
public class SimpleGuiceModule extends AbstractModule {
@Override
protected void configure() {
bind(Greeter.class).to(DefaultGreeter.class);
}
}
SimpleGuiceModule is bootstrapped by creating an Injector. The bound Greeter is retrieved, and its greeting is printed.
import com.earldouglas.guicespringjc.Greeter;
import com.google.inject.Guice;
import com.google.inject.Injector;
public class SimpleGuiceBootstrapper {
public static void main(String[] arguments) {
Injector injector = Guice.createInjector(new SimpleGuiceModule());
Greeter greeter = injector.getInstance(Greeter.class);
System.out.println(greeter.getGreeting());
}
}
The Spring JavaConfig Configuration defines a @Bean method which returns an instance of DefaultGreeter.
import org.springframework.config.java.annotation.Bean;
import org.springframework.config.java.annotation.Configuration;
import com.earldouglas.guicespringjc.DefaultGreeter;
import com.earldouglas.guicespringjc.Greeter;
@Configuration
public class SimpleSpringConfiguration {
@Bean
public Greeter greeter() {
return new DefaultGreeter();
}
}
SimpleSpringConfiguration is bootstrapped by instantiating a JavaConfigApplicationContext. The Greeter bean is retrieved, and its greeting is printed.
import org.springframework.config.java.context.JavaConfigApplicationContext;
import com.earldouglas.guicespringjc.Greeter;
public class SimpleSpringBootstrapper {
public static void main(String[] arguments) {
JavaConfigApplicationContext applicationContext = new JavaConfigApplicationContext(SimpleSpringConfiguration.class);
Greeter greeter = applicationContext.getBean(Greeter.class);
System.out.println(greeter.getGreeting());
}
}
So far the configuration, bootstrapping, and interaction with both Guice and Spring JavaConfig are quite similar in complexity and nearly identical in function. Introducing a schema-based Spring context configuration will fix that.
An XML configuration which represents both the SimpleGuiceModule and the SimpleSpringConfiguration simply defines a single bean, greeter, as an instance of DefaultGreeter.
config.xml:
<bean id="greeter" class="com.earldouglas.guicespringjc.DefaultGreeter" />
</beans>
The Guice Module binds the beans in Spring configuration using SpringIntegration.
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.google.inject.AbstractModule;
import com.google.inject.spring.SpringIntegration;
public class XmlGuiceModule extends AbstractModule {
@Override
protected void configure() {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext(
"com/earldouglas/guicespringjc/spring/config.xml");
SpringIntegration.bindAll(binder(), applicationContext);
}
}
XmlGuiceModule is bootstrapped in nearly the same way as was SimpleGuiceModule. The difference is that the Greeter is retrieved by its implementation class rather than the Greeter interface.
import com.earldouglas.guicespringjc.DefaultGreeter;
import com.earldouglas.guicespringjc.Greeter;
import com.google.inject.Guice;
import com.google.inject.Injector;
public class XmlGuiceBootstrapper {
public static void main(String[] arguments) {
Injector injector = Guice.createInjector(new XmlGuiceModule());
Greeter greeter = injector.getInstance(DefaultGreeter.class);
System.out.println(greeter.getGreeting());
}
}
The Spring JavaConfig Configuration simply leverages the @ImportXml annotation to bind the beans in Spring configuration.
import org.springframework.config.java.annotation.Configuration;
import org.springframework.config.java.annotation.ImportXml;
@Configuration
@ImportXml(locations = "classpath:com/earldouglas/guicespringjc/spring/config.xml")
public class XmlSpringConfiguration {
}
XmlSpringConfiguration is bootstrapped exactly as was SimpleSpringConfiguration.
import org.springframework.config.java.context.JavaConfigApplicationContext;
import com.earldouglas.guicespringjc.Greeter;
public class XmlSpringBootstrapper {
public static void main(String[] arguments) {
JavaConfigApplicationContext applicationContext = new JavaConfigApplicationContext(XmlSpringConfiguration.class);
Greeter greeter = applicationContext.getBean(Greeter.class);
System.out.println(greeter.getGreeting());
}
}
Guice certainly plays well with Spring, but not quite as well as Spring itself.