我有一个奇怪的问题,当我将一个单独的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注释在这种情况下不起作用?
答案 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节。在这里您可以找到声明:
容器为客户端透明地提供安全性,并发性,事务,交换到辅助存储以及会话对象的其他服务。
如果您要直接成功访问实例变量,那么您将绕过所有这些。