Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/375.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java CDI注入模棱两可的依赖项“选择任何,我不在乎”_Java_Dependency Injection_Cdi - Fatal编程技术网

Java CDI注入模棱两可的依赖项“选择任何,我不在乎”

Java CDI注入模棱两可的依赖项“选择任何,我不在乎”,java,dependency-injection,cdi,Java,Dependency Injection,Cdi,我的一个类有一个用@EJB注释声明的属性。 两个bean都符合条件,所以我得到了一个很好的org.jboss.weld.exceptions.DeploymentException:weld-001409不明确的依赖项 我知道这可以通过限定符来解决。但这会让我选择一个EJB实现而不是另一个。但我真的不在乎用哪一个。有没有一种简单的方法可以告诉CDI选择两个符合条件的实现中的任何一个,我不在乎,而且两者都很好?您可以使用实例: 。。。告诉CDI从两个符合条件的实现中选择任何一个的简单方法,我不在乎

我的一个类有一个用@EJB注释声明的属性。 两个bean都符合条件,所以我得到了一个很好的org.jboss.weld.exceptions.DeploymentException:weld-001409不明确的依赖项

我知道这可以通过限定符来解决。但这会让我选择一个EJB实现而不是另一个。但我真的不在乎用哪一个。有没有一种简单的方法可以告诉CDI选择两个符合条件的实现中的任何一个,我不在乎,而且两者都很好?

您可以使用实例:

。。。告诉CDI从两个符合条件的实现中选择任何一个的简单方法,我不在乎,两个都可以

不,没有。这与CDI试图实现的目标背道而驰。这是一个高峰,为什么

一种情况可能是您的bean是例如会话bean。在这种情况下,拥有两个适合该注入点的bean并不意味着它们都存在于您请求它们的给定时刻内。不用说,它们可能不会携带您期望它们拥有的数据/状态

另一个原因是CDI有一个底层代理系统——每个@Injected bean实际上就是该bean的代理对象。为了避免运行时出现奇怪的NPE和异常,CDI需要在启动时知道适合注入点的bean是什么

另一点可能是您可以注入的bean的不同生命周期管理。这将产生更奇怪的运行时错误

最后但并非最不重要的一点是,想象你的应用程序越来越大。有人添加了您正在注入的类型的第三个实现,而该实现并不适合您想要实现的目标。那么会发生什么

从我的头顶上看就是这样。至于方法,您可以通过BeanManager使用实例或解析。下面是一个带有实例的代码片段,这可能是更好的方法

@Inject
private Instance<Foo> foo;

public void doStuff() {
  foo.isAmbiguous(); //you can check if there are more beans eligible for injection here
  foo.isResolvable(); //yet another useful check you might want

  // there are multiple selects you can use - based on type, annotation or both
  //select based on annotation (parameter is annotation INSTANCE), with this you require a Foo type with @Default qualifier
  foo.select(Default.Literal.INSTANCE).get();

  //select based on requested type, here you are asking for a Foo bean which also has a type MyType (implements interface or extends class with that type for instance)
  foo.select(MyType.class).get(); 

  // combined - type and annotation
  foo.select(MyType.class, Default.Literal.INSTANCE).get();
}

注意:当使用实例时,方法get是实际解析的结果,并给出结果bean。

由于实例扩展了Iterable,为什么不使用迭代器返回的第一个呢?通过这样做,您不需要知道与select一起使用的X的确切子类。并不是所有你得到的豆子都适合你想要的目的。选择一个实现并使用它要安全得多。正如你所说,选择任何一个,为什么不说总是选择这个。引用最初的问题:但我真的不在乎使用哪一个。因此,选择任何实现都是完全可行的,无需决定特定的子类/限定符。当您的体系结构允许插件时,这将变得非常有用。此外,select的使用是错误的,因为它不应该获取限定符类,而应该获取该限定符的实例作为参数。select的唯一类参数应该是Foo的一个子类。我的回答是试图解释这句话,但我并不在乎使用哪一个可能不是最好的方法。答案中列出了原因。既然它被接受了,我想它就足够了。对不起,恐怕我看不出你在这里争论什么?至于资格赛,是的,你在那里犯了一个错误。谢谢,我会马上更改代码片段。
@Inject
private Instance<Foo> foo;

public void doStuff() {
  foo.isAmbiguous(); //you can check if there are more beans eligible for injection here
  foo.isResolvable(); //yet another useful check you might want

  // there are multiple selects you can use - based on type, annotation or both
  //select based on annotation (parameter is annotation INSTANCE), with this you require a Foo type with @Default qualifier
  foo.select(Default.Literal.INSTANCE).get();

  //select based on requested type, here you are asking for a Foo bean which also has a type MyType (implements interface or extends class with that type for instance)
  foo.select(MyType.class).get(); 

  // combined - type and annotation
  foo.select(MyType.class, Default.Literal.INSTANCE).get();
}