在CDI之前,EJB 3还引入了依赖注入,但这有点基础。 您可以将EJB(全状态或无状态)注入另一个EJB或Servlet(如果您的容器支持)。 当然,并不是每个应用程序都需要EJB的,这就是CDI如此受欢迎的原因。
首先,我已经举了这个例子。 有一个Payment接口和2个实现。 现金付款和签证付款。
我希望仍然可以使用相同的界面选择我注入的女巫付款类型:
public interface Payment {
void pay(BigDecimal amount);
}
这是两个实现:
public class CashPaymentImpl implements Payment {
private static final Logger LOGGER = Logger.getLogger(CashPaymentImpl.class.toString());
@Override
public void pay(BigDecimal amount) {
LOGGER.log(Level.INFO, "payed {0} cash", amount.toString());
}
}
public class VisaPaymentImpl implements Payment {
private static final Logger LOGGER = Logger.getLogger(VisaPaymentImpl.class.toString());
@Override
public void pay(BigDecimal amount) {
LOGGER.log(Level.INFO, "payed {0} with visa", amount.toString());
}
}
要注入接口,我们使用@Inject批注。 注释基本上按照它说的去做。 它注入一个组件,该组件在您的应用程序中可用。
@Inject private Payment payment;
当然,您看到的消息来自一英里远,这是行不通的。 该容器具有我们的Payment接口的2个实现,因此他不知道要注入哪个。
类型[Payment]类型的依赖关系,在注入点[[field] @Inject private be.styledideas.blog.qualifier.web.PaymentBackingAction.payment]处带有限定符[@Default]
因此,我们需要某种限定符来指出我们想要的实现。 CDI提供@Named批注,使您可以为实现命名。
@Named("cash")
public class CashPaymentImpl implements Payment {
private static final Logger LOGGER = Logger.getLogger(CashPaymentImpl.class.toString());
@Override
public void pay(BigDecimal amount) {
LOGGER.log(Level.INFO, "payed {0} cash", amount.toString());
}
}
@Named("visa")
public class VisaPaymentImpl implements Payment {
private static final Logger LOGGER = Logger.getLogger(VisaPaymentImpl.class.toString());
@Override
public void pay(BigDecimal amount) {
LOGGER.log(Level.INFO, "payed {0} with visa", amount.toString());
}
}
现在,当我们更改注入代码时,我们可以指定所需的实现。
@Inject private @Named("visa") Payment payment;
这行得通,但是灵活性受到限制。 当我们想重命名@Named参数时,我们必须在使用它的每个地方都对其进行更改。 也没有重构支持。
有一个更好的选择,可以使用@Qualifier注释使用定制注释。 让我们稍微更改一下代码。
首先,我们创建新的注释类型。
@java.lang.annotation.Documented
@java.lang.annotation.Retention(RetentionPolicy.RUNTIME)
@javax.inject.Qualifier
public @interface CashPayment {
}
@java.lang.annotation.Documented
@java.lang.annotation.Retention(RetentionPolicy.RUNTIME)
@javax.inject.Qualifier
public @interface VisaPayment {
}
添加到批注中的@Qualifier批注使此批注可由容器发现。 现在,我们可以简单地将这些注释添加到我们的实现中。
@CashPayment
public class CashPaymentImpl implements Payment {
private static final Logger LOGGER = Logger.getLogger(CashPaymentImpl.class.toString());
@Override
public void pay(BigDecimal amount) {
LOGGER.log(Level.INFO, "payed {0} cash", amount.toString());
}
}
@VisaPayment
public class VisaPaymentImpl implements Payment {
private static final Logger LOGGER = Logger.getLogger(VisaPaymentImpl.class.toString());
@Override
public void pay(BigDecimal amount) {
LOGGER.log(Level.INFO, "payed {0} with visa", amount.toString());
}
}
现在我们唯一需要做的就是将我们的注入代码更改为
@Inject private @VisaPayment Payment payment;
现在,当我们对限定符进行更改时,我们将获得不错的编译器和重构支持。 这也为API或特定于域的语言设计增加了灵活性。
参考: Java EE6 CDI,来自Styled Ideas Blog的 JCG合作伙伴 Jelle Victoor的 命名组件和限定词 。
翻译自: https://www.javacodegeeks.com/2011/10/java-ee6-cdi-named-components-and.html