java – 为什么@Singleton在Producers中超过@ApplicationScoped?

前端之家收集整理的这篇文章主要介绍了java – 为什么@Singleton在Producers中超过@ApplicationScoped?前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
LoggerProducer.java是一个用于生成要在CDI bean中注入的Logger的类:
  1. @Inject
  2. Logger LOG;

完整代码

  1. import javax.ejb.Singleton;
  2.  
  3. /**
  4. * @author rveldpau
  5. */
  6. @Singleton
  7. public class LoggerProducer {
  8.  
  9. private Map<String,Logger> loggers = new HashMap<>();
  10.  
  11. @Produces
  12. public Logger getProducer(InjectionPoint ip) {
  13. String key = getKeyFromIp(ip);
  14. if (!loggers.containsKey(key)) {
  15. loggers.put(key,Logger.getLogger(key));
  16. }
  17. return loggers.get(key);
  18. }
  19.  
  20. private String getKeyFromIp(InjectionPoint ip) {
  21. return ip.getMember().getDeclaringClass().getCanonicalName();
  22. }
  23. }

问题:@Singleton可以安全地变成@ApplicationScoped吗?

我的意思是,为什么有人想在这里使用EJB?是否存在技术原因,因为不涉及任何交易,而且(AFAIK)无论如何都是线程安全的?

我显然是指javax.enterprise.context.ApplicationScoped,而不是javax.faces.bean.ApplicationScoped.

解决方法

@Singleton注释默认情况下不仅提供事务,还提供线程安全.因此,如果您将其替换为@ApplicationScoped,您将失去同步.所以为了使它正确,你需要这样做:
  1. @ApplicationScoped
  2. public class LoggerProducer {
  3.  
  4. private final ConcurrentMap<String,Logger> loggers = new ConcurrentHashMap<>();
  5.  
  6. @Produces
  7. public Logger getProducer(InjectionPoint ip) {
  8. String key = getKeyFromIp(ip);
  9. loggers.putIfAbsent(key,Logger.getLogger(key));
  10. return loggers.get(key);
  11. }
  12.  
  13. private String getKeyFromIp(InjectionPoint ip) {
  14. return ip.getMember().getDeclaringClass().getCanonicalName();
  15. }
  16. }

如果将地图设置为静态,也可以完全没有任何范围

猜你在找的Java相关文章