是否可以将CDI Bean注入Java EE 6中的静态变量?

VWe*_*ber 3 java-ee cdi

这可能吗:

@Inject
@MessageTransport(MessageTransportType.SMS)
public static MessageSender messageSender;
Run Code Online (Sandbox Code Playgroud)

当我试图访问这个静态变量时,我得到了一个N​​PE.所以我想知道,如果一般情况下不可能的话.

提前致谢.

Vse*_*nov 10

目前这是不可能的,但理论上并非不可能.

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

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

    void something() {
        b.doTheThing();
    }
}
Run Code Online (Sandbox Code Playgroud)

Seam 2通过BijectionInterceptor支持注射.为拦截器工作Seam创建了组件的代理实例.这里,当a.something调用该方法时,它将被拦截,并且代理b实例确实将被正确地注入到a实例字段中b.如果B驻留的上下文在那一刻不活动,则注入将失败,并且a.something方法调用也将失败.

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

class A() {
    @Inject
    B b;

    void something() {
        b.doTheThing();
    }
}
Run Code Online (Sandbox Code Playgroud)

在CDI中仍有代理.但注射方式不同.CDI引入了上下文引用的概念.这是存储在a.b现场的内容.什么a.something叫做什么都没有意思.B在任何上下文中都可能没有实例,并且a.something仍然可以调用该方法.但是当涉及到调用b.doTheThing方法时 - 就在CDI开始寻找实际B实例的时候.那是有可能获得一个ContextNotActiveException例子.

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

静电注射

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

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

然而,有几个很好的用例:

  • 记录器注射,
  • 注入实体类,和
  • 注入具有钝化范围的对象.

所以我们需要在这里支持一些东西.也许这足以说:

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

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

  • 这是一个非常好的答案.只是想提出你可能想要这样做的另一个原因.如果要迁移旧版应用程序,可以使用静态注入来帮助减轻从静态到DI的过渡的痛苦. (2认同)

rdc*_*rng 5

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