2014-11-24 11 views
5

LoggerProducer.java jest klasa wykorzystywane do produkcji Przewoźnicy drewna być wstrzykiwany w CDI fasoli z:Dlaczego @Singleton nad @ApplicationScoped w producentów?

@Inject 
Logger LOG; 

pełny kod:

import javax.ejb.Singleton; 

/** 
* @author rveldpau 
*/ 
@Singleton 
public class LoggerProducer { 

    private Map<String, Logger> loggers = new HashMap<>(); 

    @Produces 
    public Logger getProducer(InjectionPoint ip) { 
     String key = getKeyFromIp(ip); 
     if (!loggers.containsKey(key)) { 
      loggers.put(key, Logger.getLogger(key)); 
     } 
     return loggers.get(key); 
    } 

    private String getKeyFromIp(InjectionPoint ip) { 
     return ip.getMember().getDeclaringClass().getCanonicalName(); 
    } 
} 

PYTANIE: Można @Singleton być bezpiecznie zamieniły się @ApplicationScoped?

To znaczy, dlaczego ktoś chciałby mieć tu EJB? Czy istnieją względy techniczne, ponieważ nie są w to zaangażowane żadne transakcje, a (AFAIK) i tak byłaby bezpieczna dla wątków?

Mam oczywiście na myśli javax.enterprise.context.ApplicationScoped, a nie javax.faces.bean.ApplicationScoped.

+0

HashMap nie wątkowo –

+0

@SME_Dev oczywiście, mój błąd polegał na tym, że '@ ApplicationScoped' jest, dzięki za komentarz BTW –

+0

@AndreaLigios możesz wyjaśnić, czy twoje pytanie dotyczy' javax.ejb.Singleton' lub 'javax.inject.Singleton'? –

Odpowiedz

12

Adnotacja @Singleton zapewnia domyślnie nie tylko transakcję, ale również bezpieczeństwo wątków. Więc jeśli zastąpisz go @ApplicationScoped, stracisz synchronizację. Tak, aby uczynić go właściwie trzeba zrobić tak:

@ApplicationScoped 
public class LoggerProducer { 

    private final ConcurrentMap<String, Logger> loggers = new ConcurrentHashMap<>(); 

    @Produces 
    public Logger getProducer(InjectionPoint ip) { 
     String key = getKeyFromIp(ip); 
     loggers.putIfAbsent(key, Logger.getLogger(key)); 
     return loggers.get(key); 
    } 

    private String getKeyFromIp(InjectionPoint ip) { 
    return ip.getMember().getDeclaringClass().getCanonicalName(); 
    } 
} 

Również można zrobić to zupełnie bez jakiegokolwiek zakresu, jeśli uczynić map jako static

+1

Krystalicznie czyste. Błędnie pamiętam, że '@ ApplicationScoped' również jest bezpieczny dla wątków, co okazuje się błędne. Myśląc o tym, jest całkowicie spójny: wszystkie EJB są bezpieczne dla wątków, wszystkie komponenty CDI nie są, nie ma wyjątków dla tego zakresu. Dziękujemy za odpowiedź –

+0

Powiązane: http://stackoverflow.com/a/14258257/1654265 –

Powiązane problemy