为什么不能注入java.util.Random?

Why can't java.util.Random be injected ?

将 java.util.Random 注入 Bean 时,部署失败:

CDI deployment failure:WELD-001408: Unsatisfied dependencies for type Random with qualifiers @Default at injection point [BackedAnnotatedField] @Inject myPackage.MyBean.random

问题:为什么不能注入 java.util.Random class 的实例?

我创建了一个 class A,它具有相似的属性(例如具有默认可见性的 final 方法),可以毫无问题地注入。这是代码:

@Named
@SessionScoped 
public class MyBean implements Serializable { 
  @Inject private java.util.Random random;   // (R) 
  @Inject private A a; 
  ...
} 

public class A implements Serializable { 
  int n; 
  public A() { System.out.println("A"); }
  public A(int n) { this.n = n; }  
  final int nextInt(int bound) { return bound -n; } 
} 

如果 (R) 行被注释掉,一切都会部署并运行良好。

您的 class 必须作为 bean 被 CDI 发现。为此你必须做这样的事情:

在其上放置一个bean 定义注解。由于 @Model 是一种刻板印象,这就是它起作用的原因。像 @Named 这样的限定符不是定义注解的 bean,这可能是它不起作用的原因。

您不能将 java.util.Random 作为 bean 注入,因为您的应用程序无法识别该给定类型的任何 bean 或生产者。

您有 beans.xml 和发现 all - 这意味着 CDI 将在您的应用程序 中 类 并尽可能将它们变成 beans (如果它们满足 CDI 规范规定的要求)。 java.util.Random 与您的应用程序 不是 ,因此 CDI 不知道如何为您实例化此类 bean 并抛出异常。另一方面,您的 A bean 在您的应用程序中,并且由于您发现 all 并且它满足要求,CDI 将认为它是一个 bean(@Dependent 范围 @Any@Default 限定词)。

为了能够注入 java.util.Random,您需要告诉 CDI 如何做到这一点。您可以使用生产者方法相当轻松地实现这一目标。请注意,生产者方法必须在 CDI bean 中声明,以便 CDI 找到它。

@Produces
@Dependent //choose desired scope, or none and it will be dependeny
// you can also add qualifiers, optional
public Random produceRandom() {
  return new Random();
}

有了上面的生产者,CDI 将不会检测到它并且能够在您需要时创建这样的对象@Inject

要将 class 作为 bean 被发现,它必须部署在 bean 存档中,请参阅 http://docs.jboss.org/cdi/spec/1.2/cdi-spec.html#bean_archive

据我了解,这也包括 target/classes 之类的内容,但 不是 rt.jar 的内容。

因为我认为您的问题只是关于一般机制而不是关于 "how-to-inject-Random",所以我就此打住。请参阅有关如何通过生产者方法使随机可注入的其他答案。