绑定注解(Binding Annotations)
Binding Annotations
在某些情况下,同一个类型可能需要多个绑定。例如,你可能同时需要PayPal credit card processor和Google Checkout processor。为了支持这种场景,Guice提供了一个可选的绑定注解。绑定注解和类型一起唯一确定一个绑定,这两者合在一起称之为一个key。
定义一个绑定直接需要两行代码和一些imports,你可以将这些定义在一个.java
文件中或者要注解的类中。
package example.pizza;
import com.google.inject.BindingAnnotation;
import java.lang.annotation.Target;
import java.lang.annotation.Retention;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import static java.lang.annotation.ElementType.PARAMETER;
import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.ElementType.METHOD;
@BindingAnnotation @Target({ FIELD, PARAMETER, METHOD }) @Retention(RUNTIME)
public @interface PayPal {}
通常你无需理解上面的这些元注解(meta annotation),但是如果你比较好奇,下面是一些简单的介绍:
@BindingAnnotation
告诉Guice这是一个绑定注解。请注意,如果多个绑定注解用在同一个变量上,Guice将会报错。@Target({FIELD, PARAMETER, METHOD})
是对用户的一种友好的帮助,它避免用户将@PayPal
注解用在它不该出现的地方。(只能用于成员变量、参数和方法上)@Retention(RUNTIME)
表示这是一个运行时注解。
然后,在使用绑定注解时,只需要将注解用在即将被Guice注入的参数上,例如:
public class RealBillingService implements BillingService {
@Inject
public RealBillingService(@PayPal CreditCardProcessor processor,
TransactionLog transactionLog) {
...
}
最后,我们需要创建一个使用注解的绑定,方法是在bind()
语句中加上annotatedWith
:
bind(CreditCardProcessor.class)
.annotatedWith(PayPal.class)
.to(PayPalCreditCardProcessor.class);
(这样,只有在注解了@PayPal
的参数或成员,才会被Guice注入PayPalCreditCardProcessor
实例)
@Named
Guice还提供了一种内置的绑定注解@Named
,它接受一个字符串作为参数:
public class RealBillingService implements BillingService {
@Inject
public RealBillingService(@Named("Checkout") CreditCardProcessor processor,
TransactionLog transactionLog) {
...
}
在使用时,通过Names.named()
创建一个实例传递给annotatedWith()
方法,就可以绑定一个具体的名字。
bind(CreditCardProcessor.class)
.annotatedWith(Names.named("Checkout"))
.to(CheckoutCreditCardProcessor.class);
这样,只有在注解了@Named("Checkout")
的参数或成员,才会被Guice注入CheckoutCreditCardProcessor
实例
但是,由于编译器无法检查@Named
中的String,因此不建议过多的使用@Named
注解。通过自定义的绑定注解来实现相同的功能是一种更好的选择,它可以保证类型安全。
带属性的绑定注解
Guice支持带属性值的绑定注解(例如@Named
)。如果在极少见的情况下,你需要使用到这样的绑定注解(并且无法使用@Provides
方法),我们建议你使用Auto/Value项目中的@AutoAnnotation
,因为实现一个这样的注解是非常容易出错的。当然,如果你确定要手动创建一个自定义的实现也是可以的,必须确保根据Annotation Javadoc
中的描述正确地实现了equals()
方法和hashCode()
方法。在这之后,将你创建的注解类的实例传入annotatedWith()
方法即可。