3

这可能吗:

@Inject
@MessageTransport(MessageTransportType.SMS)
public static MessageSender messageSender;

当我试图访问这个静态变量时,我得到了一个 NPE。所以我想知道,如果一般来说是不可能的。

提前致谢。

4

3 回答 3

10

目前是不可能的,但理论上也不是不可能。

另一个答案表明这是不可能的,但解释描述了注入在 Seam 2 中的工作方式。我将尝试从记忆中描述它。一些伪代码:

@Name("a")
class A() {
    @In
    B b;

    void something() {
        b.doTheThing();
    }
}

Seam 2 通过 BijectionInterceptor 支持注入。为了让拦截器工作,Seam 创建了组件的代理实例。在这里,当a.something方法被调用时,它会被拦截,并且代理的b实例确实会直接注入到a's instance 字段中b。如果驻留的上下文在B那一刻没有激活,那么注入就会失败,a.something方法调用也会失败。

现在让我们看一下 CDI 的类似示例:

class A() {
    @Inject
    B b;

    void something() {
        b.doTheThing();
    }
}

在 CDI 中仍然有代理。但注射的方式不同。CDI 引入了上下文引用的概念。这是存储在a.b字段中的内容。当a.something被调用时,没有任何有趣的事情发生。在任何上下文中都可能没有B实例,并且该a.something方法仍然可以正常调用。但是当涉及到调用b.doTheThing方法时——那是 CDI 开始寻找实际B实例的时候。那时就有可能获得ContextNotActiveException例如。

所以这似乎是可能的。我在旧的 Weld 网站上发现了一些有趣的注释,这可以解释为什么这还没有实现:

静态注入

静态成员的注入有几个问题:

  • 一个类可以在多个应用程序之间共享,Java EE 规范没有为此定义规则。
  • 在 Java EE 之外,很难准确定义何时注入静态成员。

尽管如此,有几个很好的用例:

  • 记录器注入,
  • 实体类的注入,以及
  • 注入到具有钝化作用域的对象中。

所以我们确实需要在这里支持一些东西。也许这样说就足够了:

  • 共享库中没有静态注入,并且
  • 在实例化 bean 的第一个实例之前注入静态字段(但非 bean 类不支持静态注入)。

有一个专门针对静态注入的开放 CDI 问题:CDI-51

于 2014-02-27T12:30:30.430 回答
5

一般不会这样做,因为静态变量不能有范围,即它只是整个类(读取应用程序)的一个,因此它没有意义,因为每个实例都会尝试根据当前范围将其设置为新值.

于 2013-10-07T12:47:42.000 回答
0

显然你不应该这样做,但有时我想你必须这样做,因为有时在某个库中有由其他东西(例如 using ServiceLoader)实例化的对象,你想注入它们。这是你可以做的一个黑客:

class StaticallyInjected {
  private static MyBean bean;

  void inject (@Observes @Initialized (ApplicationScoped.class) Object x,
               MyBean bean) {
    StaticallyInjected.bean = bean;
  }
}
于 2016-03-23T19:14:11.293 回答