NPE将Singleton bean注入Singleton bean

时间:2017-11-29 02:41:06

标签: java-ee dependency-injection ejb cdi

我有一个奇怪的问题,当我将一个单独的bean(B类)注入另一个单独的bean(A类)时,我得到一个NullPointerException,其中两个bean都在使用EJB 3.1注释。发生NPE是因为即使注入了B类,从A类访问时映射为null。 例如:

import javax.annotation.PostConstruct;
import javax.ejb.Singleton;
import javax.ejb.Startup;
import javax.inject.Inject;

@Singleton
@Startup
public class A {
    @Inject
    B b;

    @PostConstruct
    public void initialise() {
        b.map.put("test", 1);
        System.out.println("A initialised");
    }
}
import javax.annotation.PostConstruct;
import javax.ejb.Singleton;
import java.util.HashMap;

@Singleton
public class B {
    HashMap<String, Integer> map;

    @PostConstruct
    public void initialise() {
        map = new HashMap<>();
        System.out.println("B initialised");
    }
}

但是,如果我对B类使用CDI单例注释,则代码按预期执行:

import javax.annotation.PostConstruct;
import javax.inject.Singleton;
import java.util.HashMap;

@Singleton
public class B {
    HashMap<String, Integer> map;

    @PostConstruct
    public void initialise() {
        map = new HashMap<>();
        System.out.println("B initialised");
    }
}

有没有理由说明EJB注释在这种情况下不起作用?

2 个答案:

答案 0 :(得分:1)

@EJB和@Inject之间存在差异。 不幸的是,CDI和EJB注释是相似的,但可能不会以相同的方式工作!

在您的情况下,如果Bean B是CDI Bean(使用CDI Singleton注释注释),则正确注入了CDI

如果您使用@EJB而不是@Inject,我会假设EJB注入将起作用 - 如果Bean B使用javax.ejb.Singleton注释。

答案 1 :(得分:0)

许多人未能意识到的一个重要事实是,EJB客户端只能看到EJB 的公共方法的“视图”。

您正试图直接访问其中一个实例变量:

    b.map.put("test", 1);

如果向EJB B添加委托方法:

public Integer put(String key, Integer value) {
    return map.put(key, value);
}

并调用它:

@PostConstruct
public void initialise() {
    b.put("test", 1);
    System.out.println("A initialised");
}

然后你会得到

  

20:18:16,823 INFO [stdout](ServerService线程池 - 70)B初始化
  20:18:16,824 INFO [stdout](ServerService线程池 - 70)初始化

正如所料。

有关更多信息,请参阅EJB规范的第3节。在这里您可以找到声明:

  

容器为客户端透明地提供安全性,并发性,事务,交换到辅助存储以及会话对象的其他服务。

如果您要直接成功访问实例变量,那么您将绕过所有这些。