2009-11-17 12 views
8

Gli ambiti singleton/session dei bean Spring richiedono che l'accesso a tutti i suoi campi sia sincronizzato? Dì attraverso la parola chiave "sincronizzata" o usando alcune classi dal pacchetto "java.util.concurrent".Spring: ambiti Singleton/sessione e simultanea

Ad esempio, questo codice non è sicuro? (Copia/pased da 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); 
    } 
} 

risposta

21

Quando si utilizza singleton portata dal contenitore primavera, si indica che tutte le discussioni che recuperano il fagiolo dal contenitore utilizzeranno il stessa istanza. Quindi, in questo caso, in cui l'elenco degli articoli dello stato è condiviso e modificabile tra i thread, è necessario sincronizzare l'accesso all'elenco per proteggere l'applicazione da uno ConcurrentModificationException.

Tuttavia, la pratica abituale con Spring è di creare l'applicazione con oggetti senza stato, che non hanno uno stato che cambierà per tutta la durata dell'applicazione.

Nel caso dell'ambito session, è meno probabile che si verifichi un problema di concorrenza poiché il bean sarà accessibile solo dall'utente attualmente connesso. Tuttavia, è possibile (almeno sul web) avere più richieste in arrivo nella stessa sessione, nel qual caso è necessario prendere le stesse precauzioni come se il bean fosse un singleton.

Anche in questo caso il modo migliore per proteggersi è cercare di mantenere il proprio bean il meno possibile. Se si dispone di un bean che richiede uno stato, è consigliabile utilizzare l'ambito prototype, che recupera ogni volta una nuova istanza del bean dal contenitore.

0

Solo l'utente per quella sessione possono accedere a questa classe, ma ArrayList non è thread-safe, come si vede in questa discussione: http://forums.sun.com/thread.jspa?threadID=5355402

È necessario assicurarsi che la classe è completamente sicura per i thread poiché SessionScoped si limiterà a garantire che venga utilizzata solo da ogni sessione, quindi una sessione non può accedervi.

Si consiglia di guardare i commenti in questa discussione per ulteriori informazioni: http://wheelersoftware.com/articles/spring-session-scoped-beans.html

-4

Fondamentalmente per ogni utente che avvia una sessione verrà creato un nuovo ShoppingCart per tale utente per tale utente.

La tua classe è thread-safe. L'inizializzazione

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

è un'inizializzazione thread-safe e

addItem(Product item) è un'operazione atomica ed è quindi anche thread-safe.

+0

Se qualcuno chiama getItems() e inizia a scorrere su di esso, mentre allo stesso tempo un altro thread fa un addItem(), si otterrà un ConcurrentModificationException. Vedere http://java.sun.com/javase/6/docs/api/java/util/ArrayList.html per le note su ciò che deve essere sincronizzato per la sicurezza dei thread con ArrayList. –

+0

La classe non è thread-safe perché la raccolta "items" non è pubblicata in modo sicuro; items.add() non fornisce alcuna garanzia che il suo effetto sia visibile al thread oltre che attuale e non sia atomico. –

+0

Hmmm Ho avuto l'impressione che il fatto che la classe sia anche 'SessionScoped' e possa essere interpretata solo da un singolo attore all'interno del contenitore Spring assicurerebbe la sicurezza del thread della classe? –