如何确保应用程序作用域bean将在所有其他bean之前初始化



我有两个应用程序作用域bean,它们在启动时初始化。两者都用

注释
@ManagedBean(eager=true)
@ApplicationScoped

问题是,一个bean必须在另一个bean之前实例化并"postconstruct"。有办法做到这一点吗?

第一个选项将是做一个单例

@ManagedBean
@ApplicationScoped
public class SingletonBean
{
    private static SingletonBean m_oInstance;
    public static SingletonBean getInstance()
    {
        if(m_oInstance == null)
        {
            m_oInstance = (SingletonBean)FacesContext.getCurrentInstance().getExternalContext().getApplicationMap().get("singletonBean");
            // Just in case our instance is not already in the FacesContext
            if(m_oInstance == null)
            {
                m_oInstance = new SingletonBean();
                FacesContext.getCurrentInstance().getExternalContext().getApplicationMap().put("singletonBean",m_oInstance);
            }
        }
        return m_oInstance;
    }
}

你只需要从其他bean调用它:

SingletonBean.getInstance();

第二个选项我刚刚测试过,它看起来不是最优雅的,但可以完成这项工作是通过将@ManagedProperty添加到需要在second中加载的所有@ApplicationScoped bean,它允许在第一时间强制加载第一个bean。

第一bean

@ManagedBean(eager=true)
@ApplicationScoped
public class ApplicationScopeZ
{
    public ApplicationScopeZ()
    {
        System.out.println("ApplicationScopeZ - constructor");
    }
    @PostConstruct
    private void init()
    {
        System.out.println("ApplicationScopeZ - init");
    }
}

第二个bean

@ManagedBean(eager=true)
@ApplicationScoped
public class ApplicationScopeA
{
    @ManagedProperty(value="#{applicationScopeZ}")
    ApplicationScopeZ applicationScopeZ;
    public ApplicationScopeA()
    {
        System.out.println("ApplicationScopeA - constructor");
    }
    @PostConstruct
    private void init()
    {
        System.out.println("ApplicationScopeA - init");
    }
    public void setapplicationScopeZ(ApplicationScopeZ p_oApplicationScopeZ)
    {
        applicationScopeZ = p_oApplicationScopeZ;
    }
}
第三bean

@ManagedBean(eager=true)
@ApplicationScoped
public class ApplicationScopeO
{
    @ManagedProperty(value="#{applicationScopeZ}")
    ApplicationScopeZ applicationScopeZ;
    public ApplicationScopeO()
    {
        System.out.println("ApplicationScopeO - constructor");
    }
    @PostConstruct
    private void init()
    {
        System.out.println("ApplicationScopeO - init");
    }
    public void setapplicationScopeZ(ApplicationScopeZ p_oApplicationScopeZ)
    {
        applicationScopeZ = p_oApplicationScopeZ;
    }
}

使用Mojarra 2.1.14以这种配置启动应用程序,它给出如下输出:

ApplicationScopeZ - constructor
ApplicationScopeZ - init
ApplicationScopeO - constructor
ApplicationScopeO - init
ApplicationScopeA - constructor
ApplicationScopeA - init

正如我们所看到的,First bean (ApplicationScopeZ)是首先加载的,即使名称应该在末尾排序。

通过删除所有与注入相关的代码来做同样的事情,得到以下输出:

ApplicationScopeA - constructor
ApplicationScopeA - init
ApplicationScopeO - constructor
ApplicationScopeO - init
ApplicationScopeZ - constructor
ApplicationScopeZ - init

总之,注射改变了顺序

最新更新