无状态 Bean 的范围

Scope of Stateless Bean

我得到了一个如下所示的无状态 bean:

@Stateless
public class MyBean implements IMyBean {

    @Inject
    private SomeClass someClass;
    @EJB
    private MyRepository myRepository;
    @Production
    @Inject
    private SomeFacade someWorker;

    @PostConstruct
    private void init() {
       // some logic ...
    }

    // some more logic...
}

IMyBean 使用@Local 注释。 我是 运行 一个 JBoss 服务器。我有一个使用 MyBean 的 .bat 文件。只有在第一次执行这个 bat 文件时,才会调用 @PostConstruct。这是为什么?哪个范围有 MyBean?看起来它至少是 ApplicationScoped。我以为是 RequestScope...

您的 bean 在成为 CDI bean 之前是 EJB。因此它遵循无状态 EJB 的生命周期。第一次请求它时,容器会创建它并调用 @PostConstruct 回调。当不再需要它时,它不会因返回到 EJB 无状态池而被销毁,以备重用。 从 CDI 的角度来看,它是一个 @Dependent bean:每次注入它时都会重新创建它的 CDI 部分(代理),但 EJB 部分由池中的 EJB 容器提供。 查看 CDI 规范,与 Lifecycle of stateless and singleton session beans 相关的部分说明了有关创建的内容:

When the create() method of a Bean object that represents a stateless session or singleton session bean is called, the container creates and returns a container-specific internal local reference to the session bean. This reference is not directly exposed to the application.

关于破坏:

When the destroy() method is called, the container simply discards this internal reference.

内部引用被丢弃,但 EJB 容器保留 bean 以供将来重用。 如果多个用户同时请求此 bean,则可能会创建一个新的 EJB 并调用 @PostConstruct。所以从用户的角度来看,postConstruct 调用可能看起来是随机的。

最好的解决方案是将无状态 bean 放在 @ApplicationScoped 中以避免出现奇怪的行为。