CDI注入歧义依赖"选择任何,我不关心"

时间:2016-08-26 09:15:44

标签: java dependency-injection cdi

我的一个类有一个使用@EJB注释声明的属性。 两个豆子符合条件,所以我得到了一个很好的org.jboss.weld.exceptions.DeploymentException: WELD-001409 Ambiguous dependencies

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

2 个答案:

答案 0 :(得分:2)

  

...告诉CDI的一个简单方法“选择两个符合条件的实施中的任何一个,我不在乎,两者都很好”

没有。这将违背CDI试图实现的目标。这是一个高峰,为什么......

有一种情况可能是您的bean是例如会话bean。在这种情况下,为注入点设置两个拟合bean并不意味着它们在您请求它们的给定时刻内甚至存在。毋庸置疑,他们可能无法携带您期望他们拥有的数据/状态。

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

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

最后但并非最不重要的是,想象您的应用越来越大。有人添加了您正在注入的类型的第三个实现,并且对于您想要实现的目标,不精细。那会发生什么?

那就是我的头脑。至于要走的路,您可以使用Instance<MyBean>或通过BeanManager解决问题。以下是Instance的摘录,这可能是更好的方式。

@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();
}

注意:使用Instance<X>时,方法get()是实际解决方案的内容,并为您提供结果bean。

答案 1 :(得分:0)

您可以使用Instance<X>执行此操作:

@Inject
private Instance<MyEjb> myEjbs;

public void myMethod() {
    MyEjb myEjb = myEjbs.iterator().next();
    myEjb.doSomething();
}