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.