2009-11-17 29 views
8

Phạm vi đơn/phiên của hạt Spring yêu cầu quyền truy cập vào tất cả các trường của nó phải được đồng bộ hóa không? Nói thông qua từ khóa "được đồng bộ hóa" hoặc sử dụng một số lớp từ gói "java.util.concurrent".Mùa xuân: Phạm vi Singleton/phiên và đồng thời

Ví dụ: mã này có phải là chuỗi không an toàn không? (Copy/pased từ here):

@Component 
@SessionScoped 
public class ShoppingCart { 
    private List<Product> items = new ArrayList<Product>(); 

    public List<Product> getAllItems() { 
     return items; 
    } 

    public void addItem(Product item) { 
     items.add(item); 
    } 
} 

Trả lời

21

Khi bạn sử dụng singleton phạm vi từ container Spring, bạn cho biết rằng tất cả các chủ đề mà lấy đậu từ container sẽ sử dụng cùng một ví dụ. Vì vậy, trong trường hợp này, khi danh sách trạng thái của mục được chia sẻ và có thể sửa đổi giữa các chủ đề, bạn sẽ phải đồng bộ hóa quyền truy cập vào danh sách để bảo vệ ứng dụng của bạn khỏi một số ConcurrentModificationException.

Tuy nhiên, thực hành thông thường với Spring là xây dựng ứng dụng của bạn với các đối tượng không quốc tịch, không có trạng thái sẽ thay đổi trong suốt vòng đời của ứng dụng.

Trong trường hợp phạm vi session, bạn có thể ít có khả năng gặp sự cố đồng thời do người dùng hiện đã đăng nhập chỉ có thể truy cập vào bean. Tuy nhiên, nó có thể (ít nhất là trên web) để có nhiều yêu cầu đến trong cùng một phiên, trong trường hợp đó bạn sẽ cần phải thực hiện các biện pháp phòng ngừa tương tự như nếu đậu là một singleton.

Một lần nữa, cách tốt nhất để bảo vệ chính mình là cố gắng giữ cho hạt của bạn không bị trạng thái vô quốc. Nếu bạn có một bean yêu cầu trạng thái, bạn nên cân nhắc sử dụng phạm vi prototype, lần này lấy ra một cá thể mới của bean từ vùng chứa.

0

Chỉ người dùng cho phiên có thể truy cập lớp này, nhưng ArrayList không phải là thread-an toàn, như đã thấy trong cuộc thảo luận này: http://forums.sun.com/thread.jspa?threadID=5355402

Bạn cần phải đảm bảo rằng lớp của bạn hoàn toàn an toàn với luồng như SessionScoped sẽ chỉ đảm bảo rằng nó chỉ được sử dụng bởi mỗi phiên, vì vậy một phiên không thể truy cập nó.

Bạn có thể muốn xem xét các ý kiến ​​trong cuộc thảo luận này cho biết thêm: http://wheelersoftware.com/articles/spring-session-scoped-beans.html

-4

Về cơ bản đối với mỗi người dùng bắt đầu phiên, một ShoppingCart mới sẽ được tạo và phạm vi cho phiên đó cho mỗi người dùng đó.

Lớp học của bạn an toàn chỉ. Việc khởi

private List<Product> items = new ArrayList<Product>(); 

là một khởi thread-safe và

addItem(Product item) là một hoạt động nguyên tử và cũng là do thread-safe.

+0

Nếu ai đó gọi getItems() và bắt đầu lặp lại qua nó, trong khi cùng lúc một luồng khác thực hiện addItem(), bạn sẽ chặn một ConcurrentModificationException. Xem http://java.sun.com/javase/6/docs/api/java/util/ArrayList.html để biết các ghi chú về những gì cần được đồng bộ hóa cho an toàn luồng với ArrayList. –

+0

Lớp học không an toàn bởi vì bộ sưu tập 'các mục' không được xuất bản một cách an toàn; items.add() không cung cấp bất kỳ sự bảo đảm nào mà hiệu ứng của nó có thể nhìn thấy trên luồng hơn là hiện tại và nó không phải là nguyên tử. –

+0

Hmmm Tôi đã được ấn tượng rằng thực tế là lớp học cũng là 'SessionScoped' và chỉ có thể được hành động bởi một diễn viên duy nhất trong thùng chứa Spring sẽ đảm bảo an toàn luồng của lớp học? –

Các vấn đề liên quan