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
是所有已知 Fred
的 Provider
和 Iterable
,并且可以另外告诉您 (a) 它是否是 "unsatisfied"——没有生产者Fred
的——并且 (b) 它是 "resolvable"——即Fred
.
只有一位制作人
第四,在你想查看是否存在某些东西的情况下,常见的习惯用法是注入一个用你想要的类型参数化的 Instance
,然后检查它的 isResolvable()
方法。如果那个 returns true
,那么你可以调用它的 get()
方法并相信它的 return 值将是非 null
(假设它使不在 @Dependent
范围内)。
希望对您有所帮助!
在 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
是所有已知 Fred
的 Provider
和 Iterable
,并且可以另外告诉您 (a) 它是否是 "unsatisfied"——没有生产者Fred
的——并且 (b) 它是 "resolvable"——即Fred
.
第四,在你想查看是否存在某些东西的情况下,常见的习惯用法是注入一个用你想要的类型参数化的 Instance
,然后检查它的 isResolvable()
方法。如果那个 returns true
,那么你可以调用它的 get()
方法并相信它的 return 值将是非 null
(假设它使不在 @Dependent
范围内)。
希望对您有所帮助!