CDI 依赖注入可以是可选的吗?

Can CDI dependency injection be optional?

在 Spring DI 中,将自动装配字段声明为 Optional 可使客户端不向其注入任何值。这可能使用 Java EE 的 CDI 吗?我试过 Optional 但它失败了。我想知道是否有我可以使用的等效机制。

这是我尝试过的:

public class OmeletteMaker implements EggMaker{
        public static void main(String[] args){
        WeldContainer container = new Weld().initialize();
        OmeletteMaker omeletteMaker = container.instance().select(OmeletteMaker.class).get();
    }

    @Inject
    Optional<Vegetable> vegetable;
}

我收到一条错误消息: 线程 "main" org.jboss.weld.exceptions.DeploymentException 中的异常:WELD-001408 在注入点 [[BackedAnnotatedField] @Inject cafeteria.OmeletteMaker.vegetable]

具有限定符 [@Default] 的类型 [Optional] 的不满足依赖关系

这个看似简单的问题却隐藏着很多问题。我会尽量回答他们,同时牢记问题的精神。

首先,作为一般规则,如果你 @Inject 一个 Fred,那 Fred 不能是 null 除非 Fred 在 [=15] =] 范围,即使这样,生产者方法或自定义 bean 也必须显式写入 return null。存在边缘情况,但在所有现代 CDI 实现中,这是一个很好的经验法则,请牢记。

其次,Optional并不特别。从 CDI 的角度来看,Optional 只是另一个 Java 对象,所以请看我上面的第一个陈述。如果你有一些产生 Optional 的东西(比如生产者方法),那么它就不能产生 null Optional (除非再次将生产定义在 @Dependent 范围——如果你正在编写这样的方法来创建 Optional 个实例并 returning null 你肯定会让你的用户感到困惑)。如果您可以控制生成 Optional 个实例,那么您可以按照自己喜欢的方式制作它们。

第三,如果您想测试 Fred 是否有托管 bean 或某种类型的生产者,您可以像对您的问题的评论之一所指出的那样,注入一个Provider<Fred>Instance<Fred>。这些是由容器自动 "made" 的:您不必编写任何特殊的东西来自己生成它们。 Provider<Fred>Fred 实例的访问器,并且在调用其 get() 方法之前不会尝试获取实例。 Instance 是所有已知 FredProviderIterable,并且可以另外告诉您 (a) 它是否是 "unsatisfied"——没有生产者Fred 的——并且 (b) 它是 "resolvable"——即Fred.

只有一位制作人

第四,在你想查看是否存在某些东西的情况下,常见的习惯用法是注入一个用你想要的类型参数化的 Instance,然后检查它的 isResolvable() 方法。如果那个 returns true,那么你可以调用它的 get() 方法并相信它的 return 值将是非 null (假设它使不在 @Dependent 范围内)。

希望对您有所帮助!