7

这是一个在 WAS8.0 上运行的 JSF 2 应用程序。这是一页的“支持”bean的代码。

    @Named("mySessionBean")
    @SessionScoped
    @Stateful
    @LocalBean
    @StatefulTimeout(unit = TimeUnit.MINUTES, value = 10)
    public class MySessionBean implements Serializable {
        @PostConstruct
        public void init()
        {
             System.out.println("start MySessionBean: " + this.hashCode());
         }

        @PreDestroy
        public void cleanup()
        {
             System.out.println("destroy MySessionBean: " + this.hashCode());
         }
        ....
    }

web.xml 中设置的会话超时值小于 bean 的超时值。当我运行应用程序时,我看到了来自@PostConstruct 的打印输出,但从未看到来自@PreDestroy 的打印输出。我尝试了以下 2 种情况: 1. 注销 - invalidateSession;2. 只需等到会话到期。

我不是应用程序的设计者。设计者坚持把所有的backing bean作为一个有状态的session bean。我认为更主流的方法就是让它们成为 CDI bean。但无论如何,当我只将注释更改为 CDI 时,我也开始从 @PreDestroy 获取打印输出

    @Named("mySessionBean")
    @SessionScoped
    public class MySessionBean implements Serializable {
    .....

我的问题是,在第一种情况下我没有得到 @PreDestroy 方法调用的原因是什么?如果我看不到 @PreDestroy 被调用,是否有任何其他方法可以跟踪“支持”bean(在本例中为有状态会话 bean)的生命周期。谢谢!

4

2 回答 2

4

查看Java EE 6 教程的这一部分,它显示了有状态会话 bean 的生命周期。PreDestroy方法仅在从客户端代码中显式删除 bean 时调用,调用带有@Remove注释的方法。

于 2013-02-07T07:26:24.100 回答
2

另一个答案链接到Java EE 6 Tutorial,它甚至没有提到超时的存在。我也不认为该教程明确指出 @PreDestroy 方法仅在显式 @Remove 方法调用之后调用。没有说明因果关系,它只是描述了两个事件,不一定直接相关:

在生命周期结束时,客户端调用注解为@Remove 的方法,并且EJB 容器调用注解为@PreDestroy 的方法(如果有)。

WebSphere 文档提到以下内容:

当调用 remove 方法时,会为有状态会话 bean 调用 PreDestroy 生命周期拦截器回调。还要记住,如果有状态会话 bean 在处于被动状态时超时,或者在 bean 上的方法调用期间发生意外异常并且 bean 被丢弃,则不会调用 PreDestroy 生命周期拦截器回调。

现在这里它明确指出调用remove 方法时调用 PreDestroy 回调。同时它明确指出,如果 SFSB 在被动状态下超时,则不会调用 PreDestroy 回调。那么这是否意味着当 SFSB 不处于被动状态时它们会被调用?

现在让我们来看看JBoss。
首先,如果removingTimeout < idleTimeout,则存在一个关于PreDestroy 不会在删除超时时被调用的JBoss 问题。似乎已在 5.2 中修复。
其次,我刚刚在 JBoss 4.3 上进行了测试,当钝化的 SFSB 在超时时被移除时会发生什么 - 它在销毁之前被激活。

因此,对于超时和 bean 移除的行为方式,似乎存在多种解释。

于 2013-04-22T15:14:23.090 回答