绑定注解的价值
the value of binding annotations
使用绑定注解的典型例子是:-
public class RealBillingService implements BillingService {
@Inject
public RealBillingService(@PayPal CreditCardProcessor processor,
TransactionLog transactionLog) {
...
}
我想了解注释的价值,因为我无法使用另一个绑定创建另一个构造函数
public class RealBillingService implements BillingService {
@Inject
public RealBillingService(@BankABC CreditCardProcessor processor,
TransactionLog transactionLog) {
...
}
它在定义示例中看起来是多余的,所以我一定是遗漏了什么。
我可以
public class BankBillingService implements BillingService {
@Inject
public BankBillingService(@Bank CreditCardProcessor processor,
TransactionLog transactionLog) {
...
}
但是我仍然需要绑定两个(或更多)类
bind(CreditCardProcessor.class)
.annotatedWith(PayPal.class)
.to(PayPalCreditCardProcessor.class);
bind(CreditCardProcessor.class)
.annotatedWith(Bank.class)
.to(BankCreditCardProcessor.class);
并且有一堆如果这样做的话,有点否定 Guice 的价值(根据我的理解)。
绑定注解的目标是区分相同class或类型的两个不同注入密钥。在您引用的示例中:
public class RealBillingService implements BillingService {
@Inject
public RealBillingService(@PayPal CreditCardProcessor processor,
TransactionLog transactionLog) {
...
}
您可以提供替代实现:
public class StripeBillingService implements BillingService {
@Inject
public RealBillingService(@Stripe CreditCardProcessor processor,
TransactionLog transactionLog) {
...
}
或者以更高的抽象度进行操作:
public class RealBillingService implements BillingService {
@Inject
public RealBillingService(@International CreditCardProcessor processor,
TransactionLog transactionLog) {
...
}
也可以注入多个相似类型的参数:
@Inject
public RealOrderRepository(
@Customer DataStore customerDataStore,
@Order DataStore orderDataStore,
@Item DataStore itemDataStore) { /* ... */ }
作为替代方案,它会在层次结构中创建多个不必要的类型,并使创建和替换通用实现变得更加困难或不可能:
// Ideally you should have implementations like InMemoryDataStore and AwsDataStore;
// the below would force InMemoryCustomerDataStore or LocalDbItemDataStore
// regardless of whether you need them or not.
public interface CustomerDataStore extends DataStore { /* empty */ }
public interface OrderDataStore extends DataStore { /* empty */ }
public interface ItemDataStore extends DataStore { /* empty */ }
@Inject
public RealOrderRepository(
CustomerDataStore customerDataStore,
OrderDataStore orderDataStore,
ItemDataStore itemDataStore) { /* ... */ }
最终,您对绑定注解的使用应该非常少见,只是为了区分不同的注入请求,否则它们将是同一类型。在您的示例中,如果您不需要在同一应用程序中同时使用 @Bank CreditCardProcessor
和 @PayPal CreditCardProcessor
,则只需绑定 CreditCardProcessor
一次即可完成。但是,如果它们可能共存,那么您可以将它们绑定到相同的信用卡处理器,或不同的卡处理器,或者它可能需要更改。
另请参阅:Guice's BindingAnnotations docs and JSR-330's @Qualifier annotation docs
使用绑定注解的典型例子是:-
public class RealBillingService implements BillingService {
@Inject
public RealBillingService(@PayPal CreditCardProcessor processor,
TransactionLog transactionLog) {
...
}
我想了解注释的价值,因为我无法使用另一个绑定创建另一个构造函数
public class RealBillingService implements BillingService {
@Inject
public RealBillingService(@BankABC CreditCardProcessor processor,
TransactionLog transactionLog) {
...
}
它在定义示例中看起来是多余的,所以我一定是遗漏了什么。
我可以
public class BankBillingService implements BillingService {
@Inject
public BankBillingService(@Bank CreditCardProcessor processor,
TransactionLog transactionLog) {
...
}
但是我仍然需要绑定两个(或更多)类
bind(CreditCardProcessor.class)
.annotatedWith(PayPal.class)
.to(PayPalCreditCardProcessor.class);
bind(CreditCardProcessor.class)
.annotatedWith(Bank.class)
.to(BankCreditCardProcessor.class);
并且有一堆如果这样做的话,有点否定 Guice 的价值(根据我的理解)。
绑定注解的目标是区分相同class或类型的两个不同注入密钥。在您引用的示例中:
public class RealBillingService implements BillingService {
@Inject
public RealBillingService(@PayPal CreditCardProcessor processor,
TransactionLog transactionLog) {
...
}
您可以提供替代实现:
public class StripeBillingService implements BillingService {
@Inject
public RealBillingService(@Stripe CreditCardProcessor processor,
TransactionLog transactionLog) {
...
}
或者以更高的抽象度进行操作:
public class RealBillingService implements BillingService {
@Inject
public RealBillingService(@International CreditCardProcessor processor,
TransactionLog transactionLog) {
...
}
也可以注入多个相似类型的参数:
@Inject
public RealOrderRepository(
@Customer DataStore customerDataStore,
@Order DataStore orderDataStore,
@Item DataStore itemDataStore) { /* ... */ }
作为替代方案,它会在层次结构中创建多个不必要的类型,并使创建和替换通用实现变得更加困难或不可能:
// Ideally you should have implementations like InMemoryDataStore and AwsDataStore;
// the below would force InMemoryCustomerDataStore or LocalDbItemDataStore
// regardless of whether you need them or not.
public interface CustomerDataStore extends DataStore { /* empty */ }
public interface OrderDataStore extends DataStore { /* empty */ }
public interface ItemDataStore extends DataStore { /* empty */ }
@Inject
public RealOrderRepository(
CustomerDataStore customerDataStore,
OrderDataStore orderDataStore,
ItemDataStore itemDataStore) { /* ... */ }
最终,您对绑定注解的使用应该非常少见,只是为了区分不同的注入请求,否则它们将是同一类型。在您的示例中,如果您不需要在同一应用程序中同时使用 @Bank CreditCardProcessor
和 @PayPal CreditCardProcessor
,则只需绑定 CreditCardProcessor
一次即可完成。但是,如果它们可能共存,那么您可以将它们绑定到相同的信用卡处理器,或不同的卡处理器,或者它可能需要更改。
另请参阅:Guice's BindingAnnotations docs and JSR-330's @Qualifier annotation docs