LoggerProducer.java是一个类,用于生成要在CDI bean中注入的Logger:
@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 :(得分:13)
@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();
}
}
如果您将地图设为静态
,也可以完全没有任何范围