先贴一段代码,下面都用到
import javax.enterprise.inject.Produces; @SessionScoped public class Preferences implements Serializable { private PaymentStrategyType paymentStrategy; ... @Produces @Preferred public PaymentStrategy getPaymentStrategy() { switch (paymentStrategy) { case CREDIT_CARD: return new CreditCardPaymentStrategy(); case CHECK: return new CheckPaymentStrategy(); case PAYPAL: return new PayPalPaymentStrategy(); default: return null; } } }
//注入一个Producer methods @Inject @Preferred PaymentStrategy paymentStrategy;
@Produces @Preferred @SessionScoped public PaymentStrategy getPaymentStrategy() { ... }注意:Producer methods不继承声明此Producer methods的Bean的Scope.
在Producer methods一开始的实例有一个潜在的问题
CreditCardPaymentStrategy 的实现使用 Java new 运算符来实例化。
private PaymentStrategyType paymentStrategy;
而producer methods应该理解为一个独立的Bean,而paymentStrategy是从Preferences 中用new实例化的.所以我们应该使用下面这种方式来使用producer methods方法.
@Produces @Preferred @SessionScoped public PaymentStrategy getPaymentStrategy(CreditCardPaymentStrategy ccps, CheckPaymentStrategy cps, PayPalPaymentStrategy ppps) { switch (paymentStrategy) { case CREDIT_CARD: return ccps; case CHEQUE: return cps; case PAYPAL: return ppps; default: return null; } }
这里会有问题,如果CreditCardPaymentStrategy 是一个@RequestScope,那这里必然是要发生错误的.因为注入的CreditCardPaymentStrategy Bean实例是request,在@SessionScoped使用前容器就会进行销毁.那么就出错了.
这是个问题,所以我们有3种处理方案.
@Produces @Preferred @SessionScoped public PaymentStrategy getPaymentStrategy(@New CreditCardPaymentStrategy ccps, @New CheckPaymentStrategy cps, @New PayPalPaymentStrategy ppps) { switch (paymentStrategy) { case CREDIT_CARD: return ccps; case CHEQUE: return cps; case PAYPAL: return ppps; default: return null; } }这将会创建一个新的CreditCardPaymentStrategy依赖实例,传递到生产方法,依赖对象不会被摧毁,直到会话结束。
在CDI 1.1 @New限定符被弃用。CDI鼓励应用程序注入@Dependent范围bean。
@Produces @RequestScoped Connection connect(User user) { return createConnection(user.getId(), user.getPassword()); }而在一个相同的类中,disposer method可以进行匹配.
void close(@Disposes Connection connection) { connection.close(); }说明:在同一个类中,disposer method可以进行匹配类型为Connection 的Procucer methods,从而在 Procucer methods周期结束后进行jdbc的链接关闭.
import javax.enterprise.context.RequestScoped; import javax.enterprise.inject.Disposes; import javax.enterprise.inject.Produces; import javax.enterprise.inject.spi.InjectionPoint; import javax.persistence.EntityManager; import javax.persistence.EntityManagerFactory; import javax.persistence.PersistenceUnit; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class Resources { @PersistenceUnit private EntityManagerFactory entityManagerFactory; @Produces @RequestScoped protected EntityManager createEntityManager() { return entityManagerFactory.createEntityManager(); } //参数必须对应上面方法的返回值 protected void closeEntityManager(@Disposes EntityManager entityManager) { if ( entityManager.isOpen() ) { entityManager.close(); } } }
结束.