对于一个项目,我需要一个唯一的 ID 生成器。所以我想到了一个带有同步方法的单例。
由于遵循传统单例模式( private static instance
)的单例在跨 session 中共享,我想知道 @Singleton
注释的工作方式相同吗?
文档说:Identifies a type that the injector only instantiates once.
这是否意味着 @Singleton
根据 User Session
将是独立的(这对 id 生成器不利)?我应该更喜欢 old school
单例与 Class.getInstance()
通过注入(inject) @Singleton
- bean ?
或者我应该既不使用也不应该在 @ApplicationScoped
内提供服务 bean ?
必须保证只有一个独立于用户 session 的线程可以访问生成下一个 id 的方法。 (自动增量数据库 id 无法解决)
编辑:JSF 2.2、CDI 和 javax.inject.*
我在说:)
最佳答案
所有这些类型的单例( static
, @javax.inject.Singleton
, @javax.ejb.Singleton
和 @javax.enterprise.context.ApplicationScoped
)被创建 每个 JVM 一次 .
每个用户 session 创建一次的对象必须用 @javax.enterprise.context.SessionScoped
注释。所以不,每个用户 session 都不会实例化单例。
注意有两个 @Singleton
注释,javax.inject
中的一个另一个在 javax.ejb
包裹。我用它们的完全限定名称来指代它们以避免混淆。
所有这些单例之间的差异都很微妙,我不确定我是否了解所有含义,但我想到了一些:
@javax.ejb.Singleton
由 EJB 容器管理,因此它可以处理事务(@javax.ejb.TransactionAttribute
)、读/写锁定和超时(@javax.ejb.Lock
、@javax.ejb.AccessTimeout
)、应用程序启动(@javax.ejb.Startup
、@javax.ejb.DependsOn
)等. @javax.enterprise.context.ApplicationScoped
由 CDI 容器管理,因此您不会拥有 EJB 所具有的事务和锁定功能(除非您使用添加了事务的 1.0 后 CDI),但您仍然有很多不错的东西,例如 @javax.enterprise.inject.Produces
, @javax.annotation.PostConstruct
, @javax.inject.Named
, @javax.enterprise.inject.Disposes
(但其中许多特性也可用于 EJB)。 @javax.inject.Singleton
类似于 @ApplicationScoped
,除了没有代理对象(客户端将直接引用该对象)。到达真实对象的间接性会减少,但这可能会导致一些与序列化相关的问题(参见:http://docs.jboss.org/weld/reference/latest-2.2/en-US/html_single/#_the_singleton_pseudo_scope)关于static - @Singleton 与 @ApplicationScope,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26832051/