这可能吗:
@Inject
@MessageTransport(MessageTransportType.SMS)
public static MessageSender messageSender;
当我试图访问这个静态变量时,我得到了一个 NPE。所以我想知道,如果一般来说是不可能的。
提前致谢。
这可能吗:
@Inject
@MessageTransport(MessageTransportType.SMS)
public static MessageSender messageSender;
当我试图访问这个静态变量时,我得到了一个 NPE。所以我想知道,如果一般来说是不可能的。
提前致谢。
目前是不可能的,但理论上也不是不可能。
另一个答案表明这是不可能的,但解释描述了注入在 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。
一般不会这样做,因为静态变量不能有范围,即它只是整个类(读取应用程序)的一个,因此它没有意义,因为每个实例都会尝试根据当前范围将其设置为新值.
显然你不应该这样做,但有时我想你必须这样做,因为有时在某个库中有由其他东西(例如 using ServiceLoader
)实例化的对象,你想注入它们。这是你可以做的一个黑客:
class StaticallyInjected {
private static MyBean bean;
void inject (@Observes @Initialized (ApplicationScoped.class) Object x,
MyBean bean) {
StaticallyInjected.bean = bean;
}
}