Introduction
Single injector could be created from many modules, so dependecies could be separeted depends on their domain.
Combining modules
Suppose you have two modules. One describes classes using to talk with database and second provides classes for frontend. For database there are
SessionFactory interface with its implementation -
SessionFactoryImpl. The bining is defined in
DatabaseModule.
public interface SessionFactory {}
public class SessionFactoryImpl implements SessionFactory {}
public class DatabaseModule extends AbstractModule {
@Override
protected void configure() {
bind(SessionFactory.class).to(SessionFactoryImpl.class);
}
}
Widget interface is bound to
LabelWidget in
FrontendModule .
public interface Widget {}
public class LabelWidget implements Widget{}
public class FrontendModule extends AbstractModule {
@Override
protected void configure() {
bind(Widget.class).to(LabelWidget.class);
}
}
We want to have injector, which uses this two modules, so we could create it in this way:
@Test
public void shouldJoinTwoDisjointModules(){
//when
Injector sut = Guice.createInjector(new DatabaseModule(), new FrontendModule());
//then
assertNotNull(sut.getInstance(SessionFactory.class));
assertNotNull(sut.getInstance(Widget.class));
}
One constraint is that combined modules cannot have bindings for the same classes or interfaces.
Overriding modules
Suppose you have
TestSessionFactoryImpl that you want to use in your tests.
public class TestSessionFactoryImpl implements SessionFactory{}
Binding for tests is defined in
TestDatabaseModule.
public class TestDatabaseModule extends AbstractModule {
@Override
protected void configure() {
bind(SessionFactory.class).to(TestSessionFactoryImpl.class);
}
}
Tring to combine this module with your
DatabaseModule ends with
CreationException.
@Test(expected = CreationException.class)
public void shouldThrowExceptionWhenJoiningTwoModulesWithTheSameBindings(){
Guice.createInjector(new DatabaseModule(), new TestDatabaseModule());
}
To not obtain
CreationException you should tell Guice that you want to override bindings of
DatabaseModule with your
TestDatabaseModule.
@Test
public void shouldOverrideModule(){
//when
Injector sut = Guice.createInjector(Modules.override(new DatabaseModule()).with(new TestDatabaseModule()));
//then
assertEquals(TestSessionFactoryImpl.class, sut.getInstance(SessionFactory.class).getClass());
}
Conclusion
You can combine many modules during creation of injector, but only if they have no bindings for the same classes. If they have, you have to explicitly tell Guice which module overrides bindings in another module. Sources are available
here.
No comments:
Post a Comment