在 CDI 中有 @ApplicationScoped和(javax.inject) @Singleton伪作用域。他们之间有什么区别?除此之外,@ApplicationScoped是代理的,而 @Singleton不是。
@ApplicationScoped
javax.inject
@Singleton
我可以把我的 @Singleton bean 改成 @ApplicationScoped吗? @ApplicationScoped bean 可以有两个(或更多)实例吗?
@Singleton不是 CDI 规范的一部分。它是 EJB 和 javax.inject(JSR-330)的一部分。规范中没有提到它的行为,因此您只能依赖于 Weld 文档中所写的内容。
JSR-299中的 @Singleton指的是 Singleton 会话 bean (javax.ejb.Singleton,而不是 javax.inject.Singleton) ,而不是内置作用域 Singleton 中的 JSR-299管理 bean。
javax.ejb.Singleton
javax.inject.Singleton
您可能会在服务器中发现,@ApplicationScoped是每个 EAR 一个或每个 WAR/EJB-JAR 一个,因为在规范中并不清楚,但是您绝对不应该期望它是每个 JVM 一个。
使用缺省构造函数编写类的一个主要区别是在使用 javax.inject.Singleton时使用了私有访问修饰符,但是在使用 javax.enterprise.context.ApplicationScoped时,你的类应该至少使用默认访问修饰缺省构造函数,这就是 JBOSS 6.1 GA Final的实现
javax.enterprise.context.ApplicationScoped
JBOSS 6.1 GA Final
通常,当您只想拥有某个对象的一个实例时,您可能应该使用 @ApplicationScoped注释-这样的对象是代理的,因此甚至可以正确地开箱即用地序列化。
另一方面,在许多情况下,您只想要类的一个实例,但是这样的类不能被代理(例如,因为是 final)-那么 @Singleton就是一个拯救。因为 Singleton是一个伪范围,不像任何“普通”范围那样被代理。
Singleton
简而言之: 你甚至可以混合它(@Singleton和 @ApplicationScoped) ,在某些情况下它是有意义的。 (和我的一样有效!)
除了目前为止的其他答案之外,我还想在现实世界的场景中添加一些澄清的要点。
For me this question developed out of How do I force an application-scoped bean to instantiate at application startup? 在一些讨论中,我提到了这一点,但到目前为止还没有找到一个有效的反对理由:
In a lot of real-life scenarios/setups I would say it's hard to 从抽象/建模的角度来看,明确地说 某些东西是(或将成为/被视为) EJB 或应用程序范围的托管 bean
(有争议但不是决定性的)(从我的观点来看)迄今为止反对它的论据: (@BalusC 和其他所有人: 我希望看到它们是决定性的,但如果不是,上面的观点可能是正确的,尽管如此,这些论点仍然可以帮助读者获得差异/优点/缺点/不好/好的做法)
BalusC : 这是一个 EJB,而不是一个托管 bean,这是完全不同的。EJB 在后端运行,而托管 bean 在前端。EJB 也在事务上下文中运行。 你刚刚把企业 bean 和管理 bean 搞混了我刚刚指出。
但是:
我认为你不完全正确,夸大了意思/用法,在我看来这是有争议的。返回文章页面企业 JavaBeans 的 http://en.wikipedia.org/wiki/enterprise_javabeans 译者: EJB (EJB)是一种用于企业软件模块化构建的受管理服务器软件,也是多种 Java API 之一。EJB 是封装应用程序业务逻辑的服务器端基于组件的软件工程。 企业豆的种类 会话 Bean [3]可以是“有状态”、“无状态”或“单例”[ ... ] 消息驱动 Bean [ ... ]
我认为你不完全正确,夸大了意思/用法,在我看来这是有争议的。返回文章页面企业 JavaBeans 的 http://en.wikipedia.org/wiki/enterprise_javabeans 译者:
EJB (EJB)是一种用于企业软件模块化构建的受管理服务器软件,也是多种 Java API 之一。EJB 是封装应用程序业务逻辑的服务器端基于组件的软件工程。
企业豆的种类
会话 Bean [3]可以是“有状态”、“无状态”或“单例”[ ... ]
消息驱动 Bean [ ... ]
... which still holds true in my case.
BalusC : 单例 EJB 与应用程序范围内的 bean 不同。单例 EJB 是读/写锁定的,因此对于您想到的任务可能效率低下/过于复杂。长话短说: 抓住一本好的 JavaEE 书籍,并学会使用正确的工具来完成工作。一种方式肯定不是另一种方式。它能工作并不意味着它就是正确的工具。大锤能够固定螺丝,但它不一定是固定螺丝的正确工具:)
(我在这里看不到大锤-对不起...) 知道锁的默认值是好的(我没有意识到这一点) ,但是这似乎又是不正确的: < a href = “ https://docs.Oracle.com/cd/E19798-01/821-1841/gipsz/index.html”rel = “ noReferrer”> Oracle JavaEE6教程 on < em > 在单一会话 Bean 中管理并发访问
在创建单例会话 bean 时,可以通过两种方式控制对单例业务方法的并发访问: 容器管理的并发和 bean 管理的并发。 [ ... ] 尽管默认情况下,单例使用容器管理的并发,但是可以在单例的类级别添加@ConcurrencyManagement (CONTAINER)注释来显式设置并发管理类型
尽管默认情况下,单例使用容器管理的并发,但是可以在单例的类级别添加@ConcurrencyManagement (CONTAINER)注释来显式设置并发管理类型
还有一点不同: @Singleton不是 bean 定义注释,因为 Singleton作用域不是正常的作用域。 那么 @ApplicationScoped就是 bean 定义注释。
使用 CDI 1.1规范: 当应用程序处于 Discovery-mode = 注释状态时,Weld 不使用 @Singleton标识 bean,也不加载这个命令