多次构造 Eager ApplicationScoped 托管 bean

Posted

技术标签:

【中文标题】多次构造 Eager ApplicationScoped 托管 bean【英文标题】:Eager ApplicationScoped managed beans constructed multiple times 【发布时间】:2012-10-12 00:26:32 【问题描述】:

我有一堆 渴望 ApplicationScoped 托管 bean。其中一些通过ManagedProperty 注解注入其他的,形成依赖树。每个依赖的 bean 在构造后都会对其父级进行操作。

但是,似乎每次注入都会创建一个新实例,从而撤消之前的操作。据我了解,ApplicationScoped bean 应该只创建一次。我是否误解或为什么会发生这种情况?是因为他们渴望吗?

这是一个例子:

ParentBean.java

package example;

import javax.annotation.PostConstruct;
import javax.faces.bean.ApplicationScoped;
import javax.faces.bean.ManagedBean;

@ManagedBean(eager = true)
@ApplicationScoped
public class ParentBean

    static int initCount = 0;

    // ...

    @PostConstruct
    public void init()
    
        ++initCount; // Will end up being between 1 and 3. Expected always 1.

        // ...
    

Child1Bean.java

package example;

import javax.annotation.PostConstruct;
import javax.faces.bean.ApplicationScoped;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ManagedProperty;

@ManagedBean(eager = true)
@ApplicationScoped
public class Child1Bean

    @ManagedProperty("#parentBean") ParentBean parentBean;

    public ParentBean getParentBean()
    
        return parentBean;
    

    public void setParentBean(ParentBean parentBean)
    
        this.parentBean = parentBean;
    

    @PostConstruct
    public void init()
    
        // manipulate parentBean
    

Child2Bean.java

package example;

import javax.annotation.PostConstruct;
import javax.faces.bean.ApplicationScoped;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ManagedProperty;

@ManagedBean(eager = true)
@ApplicationScoped
public class Child2Bean

    @ManagedProperty("#parentBean") ParentBean parentBean;

    public ParentBean getParentBean()
    
        return parentBean;
    

    public void setParentBean(ParentBean parentBean)
    
        this.parentBean = parentBean;
    

    @PostConstruct
    public void init()
    
        // manipulate parentBean
    

【问题讨论】:

你能举个代码例子说明你是怎么做的吗? 别以为我会做任何改变,但试试@ManagedProperty(value = "#parentBean") 表达式是等价的,但我试过了。没有变化。 我没有任何注射,并且在 Tomcat7.0.53 / Mojarra 2.2.6 上遇到了同样的问题。我的应用程序范围渴望 bean 构造了 3 次。非急切的只构建一次。 【参考方案1】:

我对 Mojarra 2.0.x 也有同样的问题。我猜这个问题与多线程 JSF 初始化有关。尝试通过 com.sun.faces.enableMultiThreadedStartup 参数禁用它。

【讨论】:

谢谢,但没有效果。我的应用程序在 Mojarra 2.1.6 上运行。【参考方案2】:

我希望在 Tomcat 8 + Mojarra 2.2.0 上解决了这个问题。 就我而言,我刚刚从 web.xml 中删除了侦听器声明

<listener>
    <listener-class>com.sun.faces.config.ConfigureListener</listener-class>
</listener>

构造函数似乎在之后被调用一次。

关于监听入口,有this问题的BalusC回答的一部分。

在任何情况下,在 web.xml 中显式注册 Mojarra 的 ConfigureListener 实际上只需要解决旧的有缺陷的服务器,例如 GlassFish v3 和 Jetty,它们无法在 Mojarra 的 TLD 文件中找到侦听器。当部署到一个像样的服务器时,整个条目是不必要的。

【讨论】:

以上是关于多次构造 Eager ApplicationScoped 托管 bean的主要内容,如果未能解决你的问题,请参考以下文章

[Hibernate] - EAGER and LAZY

TF 2.3 中的错误。当混合 Eager 和 non-Eager Keras 模型时

复制构造函数被多次调用c ++

多次调用 JSF Backing Bean 构造函数

忽略关系中的 FetchType.EAGER

rails / 检查 eager_loading