Tôi có hai phiên bản của hạt CDI SessionScoped cho cùng một phiên. Tôi đã ấn tượng rằng sẽ có một ví dụ được tạo ra cho tôi bởi CDI, nhưng nó tạo ra hai. Tôi có hiểu nhầm CDI hoạt động như thế nào không, hoặc tôi có tìm thấy lỗi không?Kết quả CDI SessionScoped Bean trong hai trường hợp trong cùng một phiên
Đây là mã đậu:
package org.mycompany.myproject.session;
import java.io.Serializable;
import javax.enterprise.context.SessionScoped;
import javax.faces.context.FacesContext;
import javax.inject.Named;
import javax.servlet.http.HttpSession;
@Named @SessionScoped public class MyBean implements Serializable {
private String myField = null;
public MyBean() {
System.out.println("MyBean constructor called");
FacesContext fc = FacesContext.getCurrentInstance();
HttpSession session = (HttpSession)fc.getExternalContext().getSession(false);
String sessionId = session.getId();
System.out.println("Session ID: " + sessionId);
}
public String getMyField() {
return myField;
}
public void setMyField(String myField) {
this.myField = myField;
}
}
Đây là mã Facelet:
<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core">
<f:view contentType="text/html" encoding="UTF-8">
<h:head>
<title>Test</title>
</h:head>
<h:body>
<h:form id="form">
<h:inputText value="#{myBean.myField}"/>
<h:commandButton value="Submit"/>
</h:form>
</h:body>
</f:view>
</html>
Đây là kết quả từ việc triển khai và điều hướng đến trang:
INFO: Loading application org.mycompany_myproject_war_1.0-SNAPSHOT at /myproject
INFO: org.mycompany_myproject_war_1.0-SNAPSHOT was successfully deployed in 8,237 milliseconds.
INFO: MyBean constructor called
INFO: Session ID: 175355b0e10fe1d0778238bf4634
INFO: MyBean constructor called
INFO: Session ID: 175355b0e10fe1d0778238bf4634
Sử dụng GlassFish 3.0.1
Tôi đã thực sự cảnh báo về vấn đề trên bằng một liên quan một: gọi một phương thức không chính thức trong một constructor (hoặc khối initializer) gây ảnh hưởng ngoài ý muốn với CDI. Tôi đã đọc rằng sử dụng một phương pháp không phải là cuối cùng không được thông báo (http://download.oracle.com/javase/tutorial/java/javaOO/initial.html). Nếu tôi sử dụng một phương thức không phải cuối cùng để intialize một List trong một CDI bean thì intitializer được gọi hai lần! Lưu ý: CDI không cho phép các phương thức cuối cùng và sẽ ném một ngoại lệ thời gian chạy cho biết rằng bean không được ủy quyền. "Sửa lỗi" không gọi phương thức không phải cuối cùng và thực hiện tất cả công việc trong khối initilizer. – Ryan
Tôi đã nhận thấy rằng nếu tôi định nghĩa một phương thức init được chú thích bằng @PostConstruct thì nó chỉ được gọi một lần (mặc dù hai trường hợp của bean được tạo ra). Tôi đoán rằng CDI đang tạo ra một nhóm các cá thể của bean của tôi và gọi các post post khi nó kéo chúng ra khỏi pool. Tôi đoán việc kết hợp thể hiện của bean vẫn còn trong pool với phiên HTTP hiện tại là vô nghĩa. – Ryan
Xem phản hồi của tôi bên dưới. 2 trường hợp thứ nhất là cá thể theo ngữ cảnh, thứ 2 là proxy. Các @PostConstruct sẽ tất nhiên chỉ nhận được gọi là cho ví dụ theo ngữ cảnh và _not_ cho proxy. – struberg