7

在浏览javadoc 时FacesContext,我遇到了这句话

该实例保持活动状态,直到它的 release() 方法被调用,之后不允许进一步引用该实例。当 FacesContext 实例处于活动状态时,不得从除执行此 Web 应用程序的 servlet 容器用于处理此请求的线程之外的任何线程引用它

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

FacesContext遵循单例模式吗?在这种情况下,当多个请求同时呈现响应时它会如何表现,因为它每次只服务一个请求?

4

1 回答 1

11

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

不,你读错了。与FacesContext单个 HTTP 请求一样长。如果您在自己的代码中超出其范围的任何地方错误地引用它,它将(实际上,“可以”是一个更好的词)不会立即被 GC'ed 。例如,作为会话范围的托管 bean 的属性,它的寿命比单个 HTTP 请求长:

@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'ed。

@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后由右边创建,在方法离开前由右边销毁。因此,每个请求只有一个实例(因此不是每个应用程序)。请注意,一个 HTTP 请求算作一个单独的线程。可以有多个线程(读取:请求),因此在应用程序的生命周期中可以有多个实例。它的主要模式是外观模式,但这与它是无关的。service()FacesServletservice()FacesContextThreadLocal

也可以看看:

于 2013-04-26T12:27:30.957 回答