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

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.

解决方法

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

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

相关文章

Java中的String是不可变对象 在面向对象及函数编程语言中,不...
String, StringBuffer 和 StringBuilder 可变性 String不可变...
序列化:把对象转换为字节序列的过程称为对象的序列化. 反序...
先说结论,是对象!可以继续往下看 数组是不是对象 什么是对...
为什么浮点数 float 或 double 运算的时候会有精度丢失的风险...
面试题引入 这里引申出一个经典问题,看下面代码 Integer a ...