内部 EJB 查找:构造函数,@PostConstruct

Inside EJB lookup: constructor, @PostConstruct

我正在研究 EJB 查找的洞察力,并试图了解容器和池的工作原理。我创建了一些测试应用程序,我将对每个应用程序进行解释。

第一次实现:在构造函数中查找

    @Stateless
    public class EjbTest {

    protected EjbInjectedLocal      ejbInjected;

    public EjbTest() {
            InitialContext ic = new InitialContext();
            ejbInjected = (EjbInjectedLocal)ic.lookup("java:comp/env/ejb/EjbInjected");
            ic.close();
    }

    public void test() {
        ejbInjected.callSomeMethod();
        return;
    }

}

注入是在 class 构造函数内部执行的(不好的做法),但一切正常。构造函数检索 EJB 的代理。当我调用方法 test() 时,它被正确执行。

第二个实现:在@PostConstruct中查找

@Stateless
public class EjbTest {

    protected EjbInjectedLocal      ejbInjected;

    public EjbTest() {
    }

    @PostConstruct
    public start() {
            InitialContext ic = new InitialContext();
            ejbInjected = (EjbInjectedLocal)ic.lookup("java:comp/env/ejb/EjbInjected");
            ic.close();
    }

    public void test() {
        ejbInjected.callSomeMethod();
        return;
    }

}

作为前面的示例,查找和方法测试都工作正常。

第三种实现:构造函数内部查找和函数执行

@Stateless
public class EjbTest {

    protected EjbInjectedLocal      ejbInjected;

    public EjbTest() {
            InitialContext ic = new InitialContext();
            ejbInjected = (EjbInjectedLocal)ic.lookup("java:comp/env/ejb/EjbInjected");
            ejbInjected.callSomeMethod();
            ic.close();
    }

}

使用此实现,查找工作正常,但函数 halt/freeze 线程,因为容器尚未准备好 return 不是代理实现,而是整个 EJB 和函数无法执行。

调用构造函数时,bean还没有初始化,没有注入依赖?只有代理已 returned 但它尚不可用并且无法从池中检索整个 EJB?

Only the proxy is returned but it's not yet available and cannot be retrieved the whole EJB from the pool?

没错。你只是在这里陷入僵局。

来自 EJB specification (4.3.10.2):

Since stateless session bean instances are typically pooled, the time of the client’s invocation of the create method need not have any direct relationship to the container’s invocation of the PostConstruct/ejbCreate method on the stateless session bean instance.

这是特定于容器的行为,规范将其作为实现者创新的领域开放。实现甚至不需要使用 bean 池,任何延迟加载行为和 bean 可用的确切顺序取决于容器,就像它们为用户提供的配置一样,例如:

http://docs.jboss.org/ejb3/docs/reference/1.0.7/html/SessionBean_and_MDB_configuration.html

关于实例化期间的调用顺序,规范(第 4.3.10 节)说:

The container creates an instance of a session bean as follows. First, the container calls the bean class’s newInstance method to create a new session bean instance. Second, the container performs any dependency injection as specified by metadata annotations on the bean class or by the deployment descriptor. This includes the bean’s SessionContext, if applicable. Third, the container calls the PostConstruct lifecycle callback interceptor methods for the bean, if any. The additional steps described below apply if the session bean is invoked through the EJB 2.1 client view APIs.

特别是,此时任何依赖项注入字段(即使用 EJB 注释)都将为空。通过使用 InitialContext 你已经绕过了这个约束,这是意外行为的原因。

从您所描述的行为来看,您的容器似乎首先构建了 bean,因此 EjbInjectedLocal bean 在您尝试调用它时不可用。我很惊讶它陷入僵局,但并不奇怪它不起作用。在其他容器上尝试相同的实验并查看是否得到相同的结果会很有趣。