如何确保应用程序范围的bean将在所有其他bean之前初始化?

时间:2013-06-05 21:10:02

标签: jsf

我有两个在启动时初始化的应用程序作用域bean。两者都注明

@ManagedBean(eager=true)
@ApplicationScoped

问题是,其中一个bean必须在另一个之前进行实例化和“PostConstructed”。有没有办法实现这个目标?

1 个答案:

答案 0 :(得分:1)

第一个选项就是做一个Singleton

@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;
    }
}

你只需要从其他豆子打电话:

SingletonBean.getInstance();

第二个选项我刚刚测试过看起来不是最优雅但可以完成工作的是将@ManagedProperty添加到所有@ApplicationScoped需要在 second 中加载的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");
    }
}

第二个豆

@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;
    }
}

第三豆

@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

正如我们所看到的,首先加载第一个bean (ApplicationScopeZ),即使最后还要 的名称

通过删除所有与注入相关的代码来执行相同操作即可获得此输出:

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

总之,通过注射改变了顺序。