我可以使用 lambda 表达式通过 CDI 的策略模式动态获取 ejb 吗?

Can I use lamba experssion to obtain an ejb dynamically through strategy pattern with CDI?

我知道我可以将所有匹配接口的 bean 作为实例注入,然后以编程方式在它们之间进行选择:

@Inject @Any Instance<PaymentProcessor> paymentProcessorSource;

这意味着我必须将选择逻辑放入客户端。

作为替代方案,我可以使用带有 lambda 表达式的词法范围来缓存 ejb 的值吗?在那种情况下,容器是否能够正确管理 ejb 的生命周期,或者是否应该避免这种做法?

例如,将 PaymentProcessorImpl1 和 PaymentProcessorImpl2 作为 PaymentProcessor 的两个策略,类似这样:

public class PaymentProcessorProducer {

@Inject
private PaymentProcessorImpl1 paymentProcessorImpl1;

@Inject
private PaymentProcessorImpl2 paymentProcessorImpl2;

@Produces
private Function<String, PaymentProcessor> produce() {

    return (strategyValue) -> {

        if ("strategy1".equals(strategyValue)) {

            return paymentProcessorImpl1;

        } else if ("strategy2".equals(strategyValue)) {

            return paymentProcessorImpl2;

        } else {
            throw new IllegalStateException("Tipo non gestito: " 
                    + strategyValue);
        }

    };

}

}

然后进入客户端类似这样的事情:

@Inject
Function<String, PaymentProcessor> paymentProcessor;

...

paymentProcessor.apply("strategy1")

Can I, as an alternative, cache the value of the ejb using lexical scoping with lambda expression?

理论上,您可以这样做。好不好用,大家自己试试吧。

Will the container be able to correctly manage the lifecycle of the ejb in that case or is this practice to avoid?

这里的 EJB 到底是什么?执行PaymentProcessor?请注意,EJB bean 不同于 CDI bean。由于在 CDI 容器中不控制 EJB bean 的生命周期,它 "only provides a wrapper for you to use them as if they were CDI beans".

也就是说,生命周期仍然相同 - 在您的情况下,生产者正在创建 @Dependent bean,这意味着每次您注入 Function<String, PaymentProcessor>,生产者都会被调用。

造成某些问题的是您假设两个或多个上下文在任何给定时间处于活动状态。在您决定实际 apply() 函数的那一刻,您的实现存在的范围可能会或可能不会激活。例如,如果它们都是 ApplicationScoped,你应该没问题。但是,如果它们是 SessionScoped 并且您在应用函数之前碰巧进入了 timeout/invalidate 会话,那么您将进入一个非常奇怪的状态。

这可能就是为什么我宁愿避免这种方法并使用限定符的原因。或者您可以引入一个新的 bean,它包含两种策略,并且有一个带有参数的方法来决定使用哪种策略。