Atom Feed SITE FEED   ADD TO GOOGLE READER

Just checked in: PrivateModules

Dependency injection is addictive. The pattern allows our applications to grow without harming developer productivity. But we have seen technical hurdles...

Sometimes our modules have competing dependencies. For example, we have a BillingModule and a PermissionsModule, each of which has a private database. If we configure two PersistenceModules to talk to the two databases, the bindings conflict. Guice doesn't allow duplicate bindings to PersistenceService or any other key.

A new Guice feature is intended to address this problem. Here's the class doc from PrivateModule:

A module whose configuration information is hidden from other modules. Only bindings that are explicitly exposed will be available to other modules and to the injector. Exposed keys must be explicitly bound, either directly or via another module that's installed by the private module.

In addition to the bindings configured via configurePrivateBindings(), bindings will be created for all methods with the @Provides annotation. These bindings will be hidden from other modules unless the methods also have the @Exposed annotation:

public class FooBarBazModule extends PrivateModule {
@Override protected void configurePrivateBindings() {
bind(Foo.class).to(RealFoo.class);
expose(Foo.class);

install(new TransactionalBarModule());
expose(Bar.class).annotatedWith(Transactional.class);

bind(SomeImplementationDetail.class);
install(new MoreImplementationDetailsModule());
}

@Provides @Exposed
public Baz provideBaz() {
return new SuperBaz();
}
}

Private modules inherit type converters, scopes, and interceptors from their containing modules. They can be nested within standard modules and within other private modules using install().

Private modules are implemented on top of parent injectors. Just-in-time bindings may be created in the parent injector, sharing them with all other modules. When bindings are shared:
  • Scoped instances are shared across modules. For example, if FooImpl is a shared singleton, the other modules get the same instance.
  • Bindings that inject the Injector get the parent injector. It will not be able to get injections bound in the private module.

Just-in-time bindings will not be shared if they have dependencies in the private module. To prevent it from being shared, write an explicit binding:
  bind(FooImpl.class);

This is a part of the ongoing work for Guice 2. Get the code from Guice SVN.