Guice (pronounced 'juice') is a lightweight dependency injection framework for Java 5 and above, brought to you by Google.
We've written a piece of integration code that bridges the two IoC frameworks together. You can inject Guice defined beans into Microcontainer and/or the other way around. See examples for more details.
In this example we will define Guice module, binding simple Singleton class to one of it's instances. We will then do a contextual lookup for the Singleton instance in SingletonHolder class.
AbstractBeanMetaData guicePlugin = new AbstractBeanMetaData("GuicePlugin", GuiceKernelRegistryEntryPlugin.class.getName());
AbstractConstructorMetaData constructor = new AbstractConstructorMetaData();
AbstractArrayMetaData arrayMetaData = new AbstractArrayMetaData();
final Singleton singleton = new Singleton();
Module module = new AbstractModule()
{
protected void configure()
{
bind(Singleton.class).toInstance(singleton);
}
};
arrayMetaData.add(new AbstractValueMetaData(module));
constructor.setParameters(Collections.singletonList((ParameterMetaData)new AbstractParameterMetaData(arrayMetaData)));
guicePlugin.setConstructor(constructor);
public class SingletonHolder
{
private Singleton singleton;
@Constructor
public SingletonHolder(@Inject Singleton singleton)
{
this.singleton = singleton;
}
public Singleton getSingleton()
{
return singleton;
}
}
ControllerContext holderContext = controller.getInstalledContext("holder");
assertNotNull(holderContext);
SingletonHolder holder = (SingletonHolder)holderContext.getTarget();
assertNotNull(holder);
assertEquals(singleton, holder.getSingleton());
The detail that is hidden is in GuiceKernelRegistryEntryPlugin, which acts as a intermediate between Microcontainer's registry and Guice Injector. But all you need to do is register GuiceKernelRegistryEntryPlugin as a POJO into Microcontainer, providing Guice Modules with its constructor.
We can also go the other way around. Injecting named beans into Guice Injector. There are a couple of ways to achieve that. Lets look at them.
Injector injector = Guice.createInjector(new AbstractModule()
{
protected void configure()
{
bind(Controller.class).toInstance(controller);
bind(Singleton.class).toProvider(GuiceIntegration.fromMicrocontainer(Singleton.class, "singleton"));
bind(Prototype.class).toProvider(GuiceIntegration.fromMicrocontainer(Prototype.class, "prototype"));
}
});
AbstractBeanMetaData injectorBean = new AbstractBeanMetaData("injector", GuiceInjectorFactory.class.getName());
AbstractConstructorMetaData constructor = new AbstractConstructorMetaData();
constructor.setFactoryClass(GuiceInjectorFactory.class.getName());
constructor.setFactoryMethod("createInjector");
List<ParameterMetaData> parameters = new ArrayList<ParameterMetaData>();
parameters.add(new AbstractParameterMetaData(new AbstractDependencyValueMetaData(KernelConstants.KERNEL_NAME)));
AbstractArrayMetaData array = new AbstractArrayMetaData();
array.add(new AbstractValueMetaData(GuiceObject.ALL));
parameters.add(new AbstractParameterMetaData(array));
constructor.setParameters(parameters);
injectorBean.setConstructor(constructor);
controller.install(injectorBean);
ControllerContext injectorContext = controller.getInstalledContext("injector");
assertNotNull(injectorContext);
Injector injector = (Injector)injectorContext.getTarget();
<bean name="injector" class="org.jboss.guice.plugins.GuiceInjectorFactory">
<constructor factoryClass="org.jboss.guice.plugins.GuiceInjectorFactory" factoryMethod="createInjector">
<parameter>jboss.kernel:service=Kernel</parameter>
<parameter>
<array>
<bean name="BindAll" class="org.jboss.guice.plugins.AllGuiceObject">
<constructor factoryClass="org.jboss.guice.plugins.AllGuiceObject" factoryMethod="getInstance"/>
</bean>
</array>
</parameter>
</constructor>
</bean>
Here we see three way of usgin Microcontainer beans to do wiring in Guice. The first and second examples are purely programmatic and you need to provide a Controller instance. The third one is how you would bind all existing installed beans into Guice Injector via -beans.xml. Or you can provide a ControllerContextBindFilter instance to the binding methods to filter those beans you want to bind. See API docs for more details.