|
ProviderBindings
Provider BindingsWhen your @Provides methods start to grow complex, you may consider moving them to a class of their own. The provider class implements Guice's Provider interface, which is a simple, general interface for supplying values: public interface Provider<T> {
T get();
}Our provider implementation class has dependencies of its own, which it receives via its @Inject-annotated constructor. It implements the Provider interface to define what's returned with complete type safety: public class DatabaseTransactionLogProvider implements Provider<TransactionLog> {
private final Connection connection;
@Inject
public DatabaseTransactionLogProvider(Connection connection) {
this.connection = connection;
}
public TransactionLog get() {
DatabaseTransactionLog transactionLog = new DatabaseTransactionLog();
transactionLog.setConnection(connection);
return transactionLog;
}
}Finally we bind to the provider using the .toProvider clause: public class BillingModule extends AbstractModule {
@Override
protected void configure() {
bind(TransactionLog.class)
.toProvider(DatabaseTransactionLogProvider.class);
}If your providers are complex, be sure to test them! Throwing ExceptionsGuice does not allow exceptions to be thrown from Providers. The Provider interface does not allow for checked exception to be thrown. RuntimeExceptions may be wrapped in a ProvisionException or CreationException and may prevent your Injector from being created. If you need to throw an exception for some reason, you may want to use the ThrowingProviders extension. | |
This case is interesting. Does it really work? I am guessing that when asking Guice for BillingService? instance, it either throws runtime exception due to there is no default constructor or TransactionLog? with 'connection' attribute is null.
Can providers provide us with a singleton?
Must always test them !!!! not just when they are complex :)
I suppose you would need connection configured in module as well . If this is the module being used for Injector.
I think providers would be able to give singletons with @Singleton defined.
If you want your provider to produce instance per whatever scope, like e.g. @Singleton, just define scope when binding:
bind(TransactionLog?.class).toProvider(DatabaseTransactionLogProvider?.class).in(Singleton.class); (or any other available scope).
how about creating a Provider dynamically? I have a Class var = annotation.getValue(); and I want to create a Provider of Provider<var> but I don't know what var is until runtime. Is there a way to do that? I was looking at http://eng.wealthfront.com/2010/05/just-in-time-providers-for-guice.html which is pretty cool stuff and would work(as a different paradigm of course) but was hoping I could use straight guice with no changes to create a list of Providers instead that could provide the stuff(this is all from annotation scanning to hook up some @TriggerImpl?(xxxxx.class) on some bean.