2014-11-24 2 views
5

LoggerProducer.java является класс, используемый для производства Лесорубы, который будет введен в CDI фасоли с:Почему @Singleton над @ApplicationScoped в производителях?

@Inject 
Logger LOG; 

Полный код:

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

ВОПРОС: может @Singleton быть безопасно превращались в @ApplicationScoped?

Я имею в виду, зачем кому-то нужен EJB здесь? Существуют ли технические причины, так как не задействованы никакие транзакции, и (AFAIK) все равно будет потокобезопасным?

Я, очевидно, имею в виду javax.enterprise.context.ApplicationScoped, а не javax.faces.bean.ApplicationScoped.

+0

HashMap не потокобезопасны –

+0

@SME_Dev конечно, моя ошибка считала, что '@ ApplicationScoped', спасибо за комментарий BTW –

+0

@AndreaLigios вы можете уточнить, есть ли у вас вопрос о' javax.ejb.Singleton' или 'javax.inject.Singleton'? –

ответ

12

Аннотации @Singleton предоставляют не только транзакционную, но и поточную безопасность по умолчанию. Поэтому, если вы замените его на @ApplicationScoped, вы потеряете синхронизацию. Поэтому для того, чтобы сделать это правильно, вы должны сделать так:

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

Кроме того, вы можете сделать его полностью без каких-либо рамки, если вы сделаете карту как статические

+1

Crystal прозрачный. Я также забыл, что '@ ApplicationScoped' тоже является потокобезопасным, что оказалось неправильным. Размышляя об этом, он абсолютно последователен: все EJB являются потокобезопасными, все CDI-компоненты не являются исключением, но исключение сделано для этой области. Спасибо за ответ –

+0

Связанный: http://stackoverflow.com/a/14258257/1654265 –

Смежные вопросы