[英]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.