将 @EJB 注入显式创建的对象 -> NullPointerException
Injecting @EJB into explicitly created object -> NullPointerException
我想弄清楚对象实例化在 Java EE 中是如何工作的。我注意到,如果我尝试访问应该通过 @EJB 注入的成员,如果定义该成员的 Class 已由我而不是容器显式实例化,我会得到一个 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 中实例化哪个实现。也许还有其他方法可以做到这一点?
如果不能使用注入,获取 EJB 引用的另一种方法是使用 JNDI 来查找它。
Context initialContext = new InitialContext();
ClassB b = (ClassB)initialContext.lookup("java:global/yourappname/ClassB!com.package.containing.ClassB");
因此,您可以使用任何需要的逻辑来确定您需要的实际 ClassB 实现的 JNDI 名称,然后进行查找。
I have noticed that I get a NullPointerException if I try to access a member that is supposed to be injected through @EJB if the Class defining the member has been instantiated explicitly by me rather than the container.
这是显而易见的,因为依赖项是由容器注入的。因此,如果您正在创建实例并且没有为依赖项设置任何值,那么依赖项将为 null
。另一方面,当容器创建实例时,它还会设置其依赖项的值。
My conclusion is that even if a bean is marked to be managed it is not if one doesn't let the container instantiate it.
是的,没错。因此,当您创建实例时,该实例不受管理。
Let's say that we have the following setup, would it be possible to instantiate (explicitly) ClassB in ClassC and have ClassB invoke a method from ClassA without throwing a NullPointerException?
不,当您创建实例时,依赖项将为空。
The reason I'm looking into it is because I in my, equivalent of, ClassA need to use an EntityManager to persist some data, at the same time my ClassB is actually an interface so I need to be able to decide at runtime which implementation to instantiate in ClassC. Maybe there are other ways of doing this?
如果您需要注入特定的实现,您可以通过指定 bean 名称来实现。
@EJB(beanName="DefaultService")
private Service defautService;
@EJB(beanName="SpecificService")
private Service specificService;
参考这个link:http://www.adam-bien.com/roller/abien/entry/injecting_different_implementations_into_an
或者,如果您使用 CDI you can use @Qualifier
我想弄清楚对象实例化在 Java EE 中是如何工作的。我注意到,如果我尝试访问应该通过 @EJB 注入的成员,如果定义该成员的 Class 已由我而不是容器显式实例化,我会得到一个 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 中实例化哪个实现。也许还有其他方法可以做到这一点?
如果不能使用注入,获取 EJB 引用的另一种方法是使用 JNDI 来查找它。
Context initialContext = new InitialContext();
ClassB b = (ClassB)initialContext.lookup("java:global/yourappname/ClassB!com.package.containing.ClassB");
因此,您可以使用任何需要的逻辑来确定您需要的实际 ClassB 实现的 JNDI 名称,然后进行查找。
I have noticed that I get a NullPointerException if I try to access a member that is supposed to be injected through @EJB if the Class defining the member has been instantiated explicitly by me rather than the container.
这是显而易见的,因为依赖项是由容器注入的。因此,如果您正在创建实例并且没有为依赖项设置任何值,那么依赖项将为 null
。另一方面,当容器创建实例时,它还会设置其依赖项的值。
My conclusion is that even if a bean is marked to be managed it is not if one doesn't let the container instantiate it.
是的,没错。因此,当您创建实例时,该实例不受管理。
Let's say that we have the following setup, would it be possible to instantiate (explicitly) ClassB in ClassC and have ClassB invoke a method from ClassA without throwing a NullPointerException?
不,当您创建实例时,依赖项将为空。
The reason I'm looking into it is because I in my, equivalent of, ClassA need to use an EntityManager to persist some data, at the same time my ClassB is actually an interface so I need to be able to decide at runtime which implementation to instantiate in ClassC. Maybe there are other ways of doing this?
如果您需要注入特定的实现,您可以通过指定 bean 名称来实现。
@EJB(beanName="DefaultService")
private Service defautService;
@EJB(beanName="SpecificService")
private Service specificService;
参考这个link:http://www.adam-bien.com/roller/abien/entry/injecting_different_implementations_into_an
或者,如果您使用 CDI you can use @Qualifier