繁体   English   中英

打开页面时,CDI托管bean的构造函数被调用两次

[英]Constructor of CDI managed bean is invoked twice while opening the page

我正在尝试使用PrimeFaces的ChartBean示例。 这是观点:

<h:form>
    <p:layoutUnit position="center">             
    <p:lineChart id="linear" value="#{chartBean.linearModel}" legendPosition="e"
        title="Linear Chart" minY="0" maxY="1000" style="height:600px"/>                        
    </p:layoutUnit>
</h:form>

这是豆子:

@Named
@RequestScoped
public class ChartBean implements Serializable {

    private CartesianChartModel categoryModel;
    private CartesianChartModel linearModel;

    public ChartBean() {
        System.out.println("ChartBean constructed");
        createCategoryModel();
        createLinearModel();
    }

    // ...
}

当我运行它时,我注意到在打开页面时调用了这个bean的构造函数两次。 日志显示以下内容:

信息:ChartBean构造
信息:ChartBean构造

所以bean被实例化了两次。 这是怎么造成的,我怎么能避免这种情况? 我正在与数据库进行交互,以便在UI中显示一些数据,这样就不必两次获取数据。

第一个创建是创建bean的作用域代理的容器。 作用域代理是一个扩展bean的对象,只要其他组件需要你的bean就会被注入。 然而,它的方法不执行真正的逻辑,而是将它们的执行委托给bean的正确的事件实例。 一个例子将澄清:

假设有2个请求,R1,R2。 ChartBean ,B1和B2必须有2个实例。 假设另一个组件C依赖于ChartBean C的相关字段必须在应用程序初始化时注入ChartBean的实例,并在执行时调用正确的bean实例。 但是在应用初始化时没有请求,当然也没有B1,B2。 容器做什么? 它创建了作用域代理并将其注入任何需要它的人。 然后,每当ChartBean.method() ,在代理上调用它,它决定哪个是要调用的正确bean(对于R1为B1,对于R2为B2,如果没有请求处于活动状态,则抛出异常,例如从MessageDrivenBean调用)。

前面说过: 不要在JAVA EE组件中运行构造函数中的业务逻辑 ,因为可以从系统/容器中调用构造函数。 改为使用@PostConstruct方法:

...
public class ChartBean implements Serializable {
    public ChartBean() {
        // only construction logic here
    }
    ...
    @PostConstruct
    void postConstruct() {
        createCategoryModel();
        createLinearModel();
    }
}

顺便说一下,您可以通过在构造函数中打印类名来验证是否从代理实现中调用了构造函数:

    public ChartBean() {
        System.out.println("ChartBean as " + this.getClass().getName());
    }

它第一次被调用时,它将是你自己的其他类。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM