0

我有两个应用程序范围的 bean,它们在启动时初始化。两者都带有注释

@ManagedBean(eager=true)
@ApplicationScoped

问题是,其中一个 bean 必须在另一个之前实例化和“PostConstructed”。有没有办法做到这一点?

4

1 回答 1

1

第一个选择是做一个单例

@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调用 if :

SingletonBean.getInstance();

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

第一颗豆子

@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

总之,注射改变了顺序。

于 2013-06-05T22:33:16.407 回答