如何强制应用程序范围的bean在应用程序启动时实例化?

Jim*_*ugh 37 jsf initialization startup managed-bean

我似乎无法找到一种方法来强制在启动Web应用程序时实例化/初始化应用程序范围的托管bean.似乎应用程序范围的bean在第一次访问bean时会进行惰性实例化,而不是在启动Web应用程序时实例化.对于我的Web应用程序,当第一个用户第一次在Web应用程序中打开页面时,就会发生这种情况.

我想避免这种情况的原因是因为在我的应用程序范围的bean初始化期间发生了许多耗时的数据库操作.它必须从持久存储中检索一堆数据,然后以ListItem元素等形式缓存一些频繁显示给用户的数据.我不希望在第一个用户连接时发生这一切,因此导致长时间的延迟.

我的第一个想法是使用旧式ServletContextListener contextInitialized()方法,并从那里使用ELResolver手动请求我的托管bean的实例(从而强制初始化发生).不幸的是,我无法在此阶段使用ELResolver来触发初始化,因为ELResolver需要FacesContext并且FacesContext仅在请求的生命周期内存在.

有没有人知道另一种方法来实现这一目标?

我使用MyFaces 1.2作为JSF实现,目前无法升级到2.x.

Bal*_*usC 57

我的第一个想法是使用旧式ServletContextListener contextInitialized()方法,并从那里使用ELResolver手动请求我的托管bean的实例(从而强制初始化发生).不幸的是,我无法在此阶段使用ELResolver来触发初始化,因为ELResolver需要FacesContext并且FacesContext仅在请求的生命周期内存在.

它不需要那么复杂.只需实例化bean并将其放在应用程序作用域中,并使用相同的托管bean名称作为键.JSF将在范围内已经存在时重用 bean.使用基于Servlet API的JSF,ServletContext表示应用程序范围(HttpSession表示会话范围并HttpServletRequest表示请求范围,每个使用setAttribute()getAttribute()方法).

这应该做的,

public void contextInitialized(ServletContextEvent event) {
    event.getServletContext().setAttribute("bean", new Bean());
}
Run Code Online (Sandbox Code Playgroud)

where "bean"应该<managed-bean-name>与应用程序范围内的bean 相同faces-config.xml.


只是为了记录在案,对JSF 2.x的所有你需要做的是添加eager=true@ManagedBean@ApplicationScoped豆.

@ManagedBean(eager=true)
@ApplicationScoped
public class Bean {
    // ...
}
Run Code Online (Sandbox Code Playgroud)

然后它将在应用程序启动时自动实例化.

或者,当您通过CDI管理支持bean时@Named,请抓住OmniFaces @Eager:

@Named
@Eager
@ApplicationScoped
public class Bean {
    // ...
}
Run Code Online (Sandbox Code Playgroud)


Hei*_*löd 15

Romain Manni-Bucau在他的博客上发布了一个使用CDI 1.1的简洁解决方案.

诀窍是让bean观察内置生命周期范围的初始化,即ApplicationScoped在这种情况下.这也可以用于关机清理.所以一个例子看起来像这样:

@ApplicationScoped
public class ApplicationScopedStartupInitializedBean {
    public void init( @Observes @Initialized( ApplicationScoped.class ) Object init ) {
        // perform some initialization logic
    }

    public void destroy( @Observes @Destroyed( ApplicationScoped.class ) Object init ) {
        // perform some shutdown logic
    }
}
Run Code Online (Sandbox Code Playgroud)