原文地址:https://code.google.com/p/google-guice/wiki/InjectingProviders
InjectingProviders(注入的提供者):通过注入提供者来产生对象支持依赖注入。
和普通的依赖注入一样,每一种类型都能够确切地获取它所依赖的实例。RealBillingService包含CreditCardProcessor和TransactionLog,当灵活性是必须地时,Guice会绑定一个提供者,当调用get()方法时,提供者会产生一个对象的值。
1 2 3 |
public interface Provider<T> { T get(); } |
这个提供者的类型是通过泛型参数来区分的,在Provider和Provider之间。只要是注入值的地方都可以通过注入提供者来代替。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
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(); } } |
对每一种绑定或者是注解,注入器都有内建绑定的相应的提供者。
Providers for multiple instances(不同实例的提供者):顾名思义。
在使用提供者的过程中,你可能需要一种类型的不同实例。设想当一个披萨支付失败时,你的应用程序正在保存一个概括条目和一个详细订单。用各种提供者,你就能随时获取一个新的条目:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
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(延时加载的提供者):在提供者里做部分逻辑延迟产生大对象。
当你在获取关于一个类型的依赖,同时这个依赖的创建开销又特别的大时,你能够用提供者来推迟这项工作。当你不是非常需要这个依赖时,这是很有用的:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
public class DatabaseTransactionLog implements TransactionLog { private final Provider<Connection> connectionProvider; @Inject public DatabaseTransactionLog(Provider<Connection> connectionProvider) { this .connectionProvider = connectionProvider; } public void logChargeResult(ChargeResult result) { if (!result.wasSuccessful()) { Connection connection = connectionProvider.get(); } } |
Providers for Mixing Scopes(混合作用域的提供者):提供者产生不同作用域的对象。
依赖一个很窄的作用域的对象是一个错误,设想你使用了单例的事务日志,但是这个事务日志对当前用户需要用的是请求作用域。如果你直接注入用户就会出错,因为用户是随着请求的改变而改变的。自从提供者能够按需的产生对象值,它们使你安全的混合多个作用域成为可能:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
@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()); }
|