我试图找出对象实例化在Java EE中的工作原理。我注意到如果我尝试访问一个应该通过@EJB注入的成员,如果定义成员的类已由我而不是容器显式实例化,我会注意到我得到一个NullPointerException。我的结论是,即使bean被标记为要管理,如果没有让容器实例化它也不是。我们可以让容器管理这样的对象吗?
假设我们有以下设置,是否可以在ClassC中实例化(显式)ClassB并让ClassB从ClassA调用一个方法而不抛出NullPointerException?
@Stateless
public class ClassA {
public void bar() {
// Does something fun
}
}
@Stateless
public class ClassB {
@EJB
private ClassA A;
public void foo() {
A.bar(); // throws NullPointerException if ClassB
// is explicitly instantiated works fine
// if injected with @EJB
}
}
public class ClassC {
//@EJB // Only way to go? Can we choose an implementation of ClassB?
private ClassB B;
public ClassC() {
this.B = new ClassB(); // Bad idea? Possible??
this.B.foo();
}
}
我正在研究它的原因是因为我在我的,相当于,ClassA需要使用EntityManager来保存一些数据,同时我的ClassB实际上是一个接口所以我需要能够决定在运行时哪个实现在ClassC中实例化。也许有其他方法可以做到这一点?
答案 0 :(得分:1)
我注意到,如果我尝试访问一个应该通过@EJB注入的成员,如果定义成员的Class已经由我而不是容器显式实例化,那么我会得到一个NullPointerException。
这很明显,因为容器会注入依赖项。因此,如果您要创建实例而不为依赖项设置任何值,那么依赖项将为null
。另一方面,当容器创建实例时,它还会设置其依赖项的值。
我的结论是,即使一个bean被标记为要管理,如果没有让容器实例化它也不是。
是的,这是正确的。因此,在创建实例时,实例将不受管理。
让我们说我们有以下设置,是否可以在ClassC中实例化(显式)ClassB并让ClassB从ClassA调用一个方法而不抛出NullPointerException?
不,当您创建实例时,依赖项将为null。
我调查它的原因是因为我在我的,相当于,ClassA需要使用EntityManager来保存一些数据,同时我的ClassB实际上是一个接口所以我需要能够在运行时决定在ClassC中实例化哪个实现。也许有其他方法可以做到这一点?
如果需要注入特定的实现,可以通过指定bean名称来实现。
@EJB(beanName="DefaultService")
private Service defautService;
@EJB(beanName="SpecificService")
private Service specificService;
请参阅此链接:http://www.adam-bien.com/roller/abien/entry/injecting_different_implementations_into_an
或者,如果您正在使用CDI,则可以使用@Qualifier
答案 1 :(得分:0)
如果不能使用注入,获取EJB引用的另一种方法是使用JNDI进行查找。
Context initialContext = new InitialContext();
ClassB b = (ClassB)initialContext.lookup("java:global/yourappname/ClassB!com.package.containing.ClassB");
因此,您可以使用所需的任何逻辑来确定所需的实际ClassB实现的JNDI名称,然后查找它。