我有一个无状态的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 ......
答案 0 :(得分:4)
在成为CDI bean之前,您的bean是一个EJB。因此它遵循无状态EJB的生命周期。第一次请求时,容器会创建它并调用@PostConstruct
回调。当它不再需要时,它不会被返回到EJB无状态池而被破坏,准备重用。
从CDI的角度来看,它是一个@Dependent
bean:每次注入时都会重新创建CDI部分(代理),但EJB部分是由池中的EJB容器提供的。
查看CDI规范,与Lifecycle of stateless and singleton session beans相关的部分说明了有关创建的内容:
当一个Bean对象的create()方法表示无状态 调用session或singleton会话bean,容器创建和 返回会话的特定于容器的内部本地引用 豆。此引用不直接暴露给应用程序。
关于破坏:
调用destroy()方法时,容器只会丢弃 这个内部参考。
内部引用被丢弃,但EJB容器保留bean以供将来重用。
如果多个用户同时请求此bean,则可能会创建一个新EJB并调用@PostConstruct
。所以从用户的角度来看,postConstruct调用可能看起来是随机的。
最好的解决方案是将您的无状态bean放在@ApplicationScoped
中,以避免出现奇怪的行为。