单例 CDI @Inject 空指针异常

Singleton CDI @Inject null pointer exception

我需要使用依赖注入从某些 ejb(无状态和单例)触发事件。我不使用 Spring、Guice 等。 问题是当通过 getInstance() 调用它的方法时,我在其中一个 bean 中得到了 NPE。这是代码片段:

@Stateless
@LocalBean
public class ControllerStartStop {
    @Inject
    private Event<SomeWebMessage> webEvent; 

    public String startCircle(String passwordP, String passwordH) {
    .........
    String res = "some msg";
    webEvent.fire(new SomeWebMessage(res, 0));   // this works fine
    MainDay.getInstance().startDay();      // NullPointerException

这是 MainDay 单例:

@Singleton
public class MainDay {
    private static final MainDay mDay = new MainDay();
    public static MainDay getInstance() {   return mDay ;   }

    @Inject
    private Event<SomeWebMessage> webEvent; 

    public void startDay() {
        String s = new String("MainDay");
        webEvent.fire(new SomeWebMessage(s,0));   // NullPointerException

beans.xml 在 META-INF 中:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://xmlns.jcp.org/xml/ns/javaee"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee 
                           http://xmlns.jcp.org/xml/ns/javaee/beans_1_1.xsd"
       version="1.1" bean-discovery-mode="all">

</beans>

当我从像 MainDay.initDS() 这样的静态方法调用中触发事件时,或者当调度程序调用方法 startDay() 时(@Schedule(hour = " ", 分钟 = "", 秒 = "/10")*。 不知道是什么原因

注意 @Singleton 意味着容器(EJB 或 CDI,取决于它是哪个注释)将管理实例,即 you 不应该创建它你自己。

如果您通过 private static final MainDay mDay = new MainDay(); 创建实例,容器将不会进行任何注入,因此 webEvent 将为空。除此之外,容器不会知道该实例,并且在其他地方使用 @Inject MainDay 很可能会产生另一个实例。

因此直接使用注入(或查找,如果需要):

class ControllerStartStop  {
  @Inject
  private MainDay mDay;

  ...
  public String startCircle(String passwordP, String passwordH) {
    ...
    String res = "some msg";
    webEvent.fire(new SomeWebMessage(res, 0)); 
    mDay.startDay();    
    ...
  }

There is no NPE when I fire event from a call of static method like MainDay.initDS() or when method startDay() is invoked by a Sheduler (@Schedule(hour = "", minute = "", second = "/10")*. I have no idea what is the reason

在不知道您的代码的情况下,这只是一个猜测,但我假设您在此处注入 MainDay 或使用 CDI/JNDI 查找。因此,如果有 none,容器将创建一个实例,并将注入 Event 个对象。

NPE 1:

目标 EJB MainDay "observe" 事件不应该调用它的 startDay() 方法吗?

public void onEvent(@Observes SomeWebMessage event) {
    // if (...)
        startDay();
}

因此不需要静态 getInstance() 方法。

NPE 2:

@Inject Event<SomeWebMessage> webEvent; 

依赖注入 (DI) 只工作,如果你 不是 手动调用构造函数 new MainDay() 但注入所需 bean 的实例并让 DI 容器处理构造.

但是使用 @Observes (javax.enterprise.event.Observes) 你应该能够移除所有臭味 static 东西。