Guice系列之用户指南(十二)

简介:

原文地址: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();

/* use the processor and transaction log here */

}

}

对每一种绑定或者是注解,注入器都有内建绑定的相应的提供者。

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) {

/* only write failed charges to the database */

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());

}


相关文章
【JavaSE】Java基础语法(十九):接口新特性
1. 接口组成更新概述 常量:接口可以定义全局常量,使用关键字public static final修饰。 抽象方法:接口中可以定义抽象方法,使用关键字public abstract修饰。实现类必须实现接口的所有抽象方法。
|
XML 安全 Java
JavaSE基础面试题(精简版)
把CPU处理器与操作系统的整体叫平台
57 0
【JavaSE】Java基础语法(十八):接口
1. 接口的概述 接口就是一种公共的规范标准,只要符合规范标准,大家都可以通用。 Java中接口存在的两个意义 用来定义规范 用来做功能的拓展