Java EE6 CDI,命名组件和限定符

Java EE6的最大承诺之一就是简化了依赖注入的使用。 他们做到了,使用CDI 。 CDI代表Java EE的上下文和依赖注入,它提供了一个基础集,用于在企业应用程序中应用依赖注入。

在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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值