Author: limpbizkit
Date: Mon Mar  2 21:10:58 2009
New Revision: 897

Added:
    wiki/InjectingProviders.wiki

Log:
Created wiki page through web user interface.

Added: wiki/InjectingProviders.wiki
==============================================================================
--- (empty file)
+++ wiki/InjectingProviders.wiki        Mon Mar  2 21:10:58 2009
@@ -0,0 +1,98 @@
+==Injecting Providers==
+With normal dependency injection, each type gets exactly *one instance* of  
each of its dependent types. The `RealBillingService` gets one  
`CreditCardProcessor` and one `TransactionLog`. When this flexibility is  
necessary, Guice binds a provider. Providers produce a value when the  
`get()` method is invoked:
+{{{
+public interface Provider<T> {
+  T get();
+}
+}}}
+The provider's type is _parameterized_ to differentiate a  
`Provider<TransactionLog>` from a `Provider<CreditCardProcessor>`. Wherever  
you inject a value you can inject a provider for that value.
+{{{
+public class RealBillingService implements BillingService {
+  private final Provider<CreditCardProcessor> processorProvider;
+  private final Provider<TransactionLog> transactionLogProvider;
+
+  @Inject
+  public RealBillingService(Provider<CreditCardProcessor>  
processorProvider,
+      Provider<TransactionLog> transactionLogProvider) {
+    this.processorProvider = processorProvider;
+    this.transactionLogProvider = transactionLogProvider;
+  }
+
+  public Receipt chargeOrder(PizzaOrder order, CreditCard creditCard) {
+    CreditCardProcessor processor = processorProvider.get();
+    TransactionLog transactionLog = transactionLogProvider.get();
+
+    /* use the processor and transaction log here */
+  }
+}
+}}}
+For every binding, annotated or not, the injector has a built-in binding  
for its provider.
+
+
+==Providers for multiple instances==
+Use providers when you need multiple instances of the same type. Suppose  
your application saves a summary entry and a details when a pizza charge  
fails. With providers, you can get a new entry whenever you need one:
+{{{
+public class LogFileTransactionLog implements TransactionLog {
+
+  private final Provider<LogFileEntry> logFileProvider;
+
+  @Inject
+  public LogFileTransactionLog(Provider<LogFileEntry> logFileProvider) {
+    this.logFileProvider = logFileProvider;
+  }
+
+  public void logChargeResult(ChargeResult result) {
+    LogFileEntry summaryEntry = logFileProvider.get();
+    summaryEntry.setText("Charge " +  
(result.wasSuccessful() ? "success" : "failure"));
+    summaryEntry.save();
+
+    if (!result.wasSuccessful()) {
+      LogFileEntry detailEntry = logFileProvider.get();
+      detailEntry.setText("Failure result: " + result);
+      detailEntry.save();
+    }
+  }
+}}}
+
+
+==Providers for lazy loading==
+If you've got a dependency on a type that is particularly *expensive to  
produce*, you can use providers to defer that work. This is especially  
useful when you don't always need the dependency:
+{{{
+public class DatabaseTransactionLog implements TransactionLog {
+
+  private final Provider<Connection> connectionProvider;
+
+  @Inject
+  public DatabaseTransactionLog(Provider<Connection> connectionProvider) {
+    this.connectionProvider = connectionProvider;
+  }
+
+  public void logChargeResult(ChargeResult result) {
+    /* only write failed charges to the database */
+    if (!result.wasSuccessful()) {
+      Connection connection = connectionProvider.get();
+    }
+  }
+}}}
+
+==Providers for Mixing Scopes==
+It is an error to depend on an object in a _narrower_ scope. Suppose you  
have a singleton transaction log that needs on the request-scoped current  
user. Should you inject the user directly, things break because the user  
changes from request to request. Since providers can produce values  
on-demand, they enable you to mix scopes safely:
+{{{
+...@singleton
+public class ConsoleTransactionLog implements TransactionLog {
+
+  private final AtomicInteger failureCount = new AtomicInteger();
+  private final Provider<User> userProvider;
+
+  @Inject
+  public ConsoleTransactionLog(Provider<User> userProvider) {
+    this.userProvider = userProvider;
+  }
+
+  public void logConnectException(UnreachableException e) {
+    failureCount.incrementAndGet();
+    User user = userProvider.get();
+    System.out.println("Connection failed for " + user + ": " +  
e.getMessage());
+    System.out.println("Failure count: " + failureCount.incrementAndGet());
+  }
+}}}

--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups 
"google-guice-dev" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to 
[email protected]
For more options, visit this group at 
http://groups.google.com/group/google-guice-dev?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to