问题描述
是用于生成要通过以下方式注入CDI bean的Logger的类:
LoggerProducer.java is a class used to produce Loggers to be injected in CDI beans with:
@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
吗?
QUESTION: can @Singleton
be safely turned into @ApplicationScoped
?
I是什么意思,为什么有人在这里想要EJB?有技术上的原因,因为不涉及任何事务,并且(AFAIK)无论如何都是线程安全的?
I mean, why would anyone want an EJB here ? Are there technical reasons, since no transactions are involved, and (AFAIK) it would be thread-safe anyway ?
推荐答案
默认情况下, @Singleton
注释不仅提供事务处理,而且还提供线程安全性。因此,如果将其替换为 @ApplicationScoped
,则会失去同步。因此,为了使其正确运行,您需要执行以下操作:
The @Singleton
annotation provides not only transaction but also thread-safety by default. So if you will replace it with @ApplicationScoped
, you will loose the synchronization. So in order to make it properly you need to do like this:
@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();
}
}
如果您没有任何限制,也可以完全做到这一点将地图设为静态
Also you can make it completely without any scope if you make the map as static
这篇关于为什么生产者中@Singleton优于@ApplicationScoped?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!