2014-11-24 21 views
5

LoggerProducer.java là một lớp được sử dụng để sản xuất Loggers được tiêm trong đậu CDI với:Tại sao @Singleton trên @ApplicationScoped in Producers?

@Inject 
Logger LOG; 

Full mã:

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(); 
    } 
} 

HỎI: có thể @Singleton được một cách an toàn biến thành @ApplicationScoped?

Ý tôi là, tại sao mọi người lại muốn có EJB ở đây? Có lý do kỹ thuật nào không, vì không có giao dịch nào có liên quan, và (AFAIK) nó có an toàn không?

Tôi rõ ràng đang đề cập đến javax.enterprise.context.ApplicationScoped, không phải là javax.faces.bean.ApplicationScoped.

+0

HashMap không threadsafe –

+0

@SME_Dev tất nhiên, lỗi của tôi đã nghĩ rằng '@ ApplicationScoped' là, cảm ơn cho các bình luận BTW –

+0

@AndreaLigios bạn có thể làm rõ cho dù câu hỏi của bạn là về' javax.ejb.Singleton' hoặc 'javax.inject.Singleton'? –

Trả lời

12

Chú thích @Singleton không chỉ cung cấp giao dịch mà còn đảm bảo an toàn theo luồng. Vì vậy, nếu bạn sẽ thay thế nó bằng @ApplicationScoped, bạn sẽ mất đồng bộ hóa. Vì vậy, để làm cho nó đúng cách bạn cần phải làm như thế này:

@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(); 
    } 
} 

Ngoài ra bạn có thể làm cho nó hoàn toàn không có bất kỳ phạm vi nếu bạn thực hiện bản đồ như tĩnh

+1

Tinh thể rõ ràng. Tôi cũng đã nhầm lẫn '@ ApplicationScoped' là luồng an toàn, điều này hóa ra là sai. Nghĩ về nó, nó hoàn toàn mạch lạc: tất cả các EJB đều là chủ đề an toàn, tất cả các hạt CDI đều không phải là ngoại lệ cho phạm vi này. Cảm ơn câu trả lời –

+0

Liên quan: http://stackoverflow.com/a/14258257/1654265 –

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