这可能吗:
@Inject
@MessageTransport(MessageTransportType.SMS)
public static MessageSender messageSender;
当我尝试访问此静态变量时,我正在获取NPE。所以我想知道,如果一般情况下不可能的话。
提前致谢。
答案 0 :(得分:9)
目前不可能,但理论上并非不可能。
另一个答案表明这是不可能的,但是解释描述了Seam 2中注入的工作方式。我将尝试从内存中描述它。一些伪代码:
@Name("a")
class A() {
@In
B b;
void something() {
b.doTheThing();
}
}
Seam 2通过BijectionInterceptor支持注射。为拦截器工作Seam创建了组件的代理实例。在这里,当调用a.something
方法时,它将被截获,并且代理的b
实例确实将被注入a
的实例字段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网站上找到some interesting notes,这可以解释为什么还没有实现:
静态注射
注入静态成员有几个问题:
- 一个类可以在多个应用程序之间共享,而Java EE规范没有为此定义规则。
- 在Java EE之外,很难准确定义何时注入静态成员。
然而,有几个很好的用例:
- logger injection,
- 注入实体类,
- 注入具有钝化范围的对象。
所以我们需要在这里支持一些东西。也许这足以说:
- 共享库中没有静态注入,
- 在实例化bean的第一个实例之前注入静态字段(但是非bean类不支持静态注入)。
有一个专门针对静态注入的开放CDI问题:CDI-51。
答案 1 :(得分:5)
一般情况下没有完成,因为静态变量不能有一个范围,即它只是整个类的一个(读取应用程序),因此它没有意义,因为每个实例都会尝试将其设置为基于的新值目前的范围。
答案 2 :(得分:0)
显然你不应该这样做,但有时我认为你必须这样做,因为有时在某些图书馆中存在被其他东西(例如使用ServiceLoader
)实例化的对象并且你想要注入它们。这是你可以做的黑客攻击:
class StaticallyInjected {
private static MyBean bean;
void inject (@Observes @Initialized (ApplicationScoped.class) Object x,
MyBean bean) {
StaticallyInjected.bean = bean;
}
}