FacesContext 的生命周期是什么?

7

在阅读FacesContext的javadoc时,我遇到了这句话

该实例保持活动状态,直到调用其release()方法,此后不允许再引用此实例。在FacesContext实例处于活动状态时,不能从除处理此请求的servlet容器所使用的线程之外的任何线程引用它。

这是否意味着FacesContext永远不会进行垃圾收集,只有在当前Web应用程序停止(服务器停止)时才会销毁实例?

FacesContext是否遵循单例模式?在这种情况下,当多个请求同时请求渲染响应时,它将如何运作,因为它每次只服务于一个请求?

1个回答

12
这是否意味着FacesContext永远不会被垃圾回收,只有当当前Web应用程序停止(服务器关闭)时才会销毁实例?
不是的,你理解错了。 FacesContext的寿命仅限于单个HTTP请求的时间。如果在代码范围之外错误引用它(例如作为超出单个HTTP请求寿命的会话作用域托管bean的属性),则它将(实际上,“可以”更准确)不会立即被GC回收。
@ManagedBean
@SessionScoped
public class BadSessionBean {

    // Bad Example! Never do this! Not threadsafe and instance can't be GC'ed by end of request!
    private FacesContext context = FacesContext.getCurrentInstance();

}

如果你在代码中没有这样做,因此你总是在方法本地范围内获取当前实例,那么它将有机会被正确地GC回收。
@ManagedBean
@SessionScoped
public class GoodSessionBean {

    public void someMethod() {
        // OK! Declared in method local scope and thus threadsafe.
        FacesContext context = FacesContext.getCurrentInstance();
    }

}

请注意,这种GC行为不仅适用于JSF/FacesContext,而是一般适用于基本的Java。
“FacesContext”是否遵循单例模式?如果是这样,当多个请求同时到达以渲染响应时,它将如何行事,因为它一次只能服务一个请求? 不,它绝对不是单例。它是ThreadLocal实例,由FacesServlet在进入service()方法后立即创建,并由FacesServlet在离开service()方法前销毁。因此,每个请求只有一个实例(因此不是每个应用程序)。请注意,一个HTTP请求计为一个单独的线程。在应用程序的生命周期中可以有多个线程(即:请求),因此可以有多个FacesContext实例。它的主要模式是facade pattern,但这与它是ThreadLocal无关。 另请参见:

请注意,一个HTTP请求算作一个单独的线程。可以有多个线程(也就是请求),因此在应用程序的生命周期内可以有多个FacesContext实例。谢谢深入解释,我一直在寻找这句话 :) - Ullas
那么,在这种情况下,不建议在会话范围的bean中获取FacesContext的实例?因为按照规则,FacesContext的实例不应该在两个请求之间共享。 - Ullas
请注意,被销毁的只是对象引用,而不是上下文实例本身。现在所有的部分都已经拼凑在一起了,我强烈建议您暂停JSF并花些时间学习Java基础知识。像Oracle官方教程和SCJP书籍这样的合理的基础Java教程也会涵盖GC和对象引用的相关内容。 - BalusC
我很久以前收藏了你关于Servlets解释的链接..:) - Ullas
阅读那个答案,我有这样的印象:在一个会话作用域的托管bean中,每个方法都有不同的请求。是这样吗? - Luciane
显示剩余3条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接