@ApplicationScoped 必须是可序列化的?

@ApplicationScoped must be Serializable?

我现在正在学习 Java EE 7 tutorial 中的 CDI 范围,并发现在最后一段中它说

Beans that use session, application, or conversation scope must be serializable, but beans that use request scope do not have to be serializable.

但让我很困惑的是,在我的 IDE(Netbeans 和 IntelliJ Idea)中,当我使用 @SessionScoped 或 @ConversationScoped 时,如果我没有实现 Serializable,它确实会给我一个错误就像 Java EE 7 教程所说的那样,显然,我无法构建项目然后 运行 它。当我使用 @ApplicationScoped 但没有实现 Serializable 时,事情变得很奇怪,没有错误出现,然后我可以正常构建 运行 应用程序。

所以我对此很好奇,真的很想知道为什么。你能解释一下那里发生了什么吗?非常感谢!

显示您的 IDE 中的错误基本上是因为您的 IDE 有一些插件(顺便说一句,不能 100% 信任它)。

连载原因如下:

  • @SessionScoped豆子

    • 这些不仅仅由 CDI 规范处理,其他规范也对它们有要求
    • 即容器可以选择存储钝化session以节省资源
    • 另一个故事是服务器之间的复制,因此您的请求可以在多个节点上处理(故障转移场景等)
    • 我们不知道为什么,但正因为如此,我们必须确保此类 bean 始终可序列化
  • @ConversationScoped豆子

    • 几乎是一样的故事,不是说其他​​规范对它们有要求,而是这些 bean 'live' 在会话范围内并且可以与会话一样长地存在(如果不早点结束)
    • 由于这些原因,当服务器 passivates/replicates 一个会话连同会话范围的 bean 时,它当然也必须 passivate/replicate 会话范围的 bean
  • @ApplicationScoped豆子

    • 这些确实应该是可序列化的,但在某些情况下,即使它们不是
    • ,您的应用程序也能正常工作
    • 这些情况是您可以避免序列化的时候,例如运行 在单节点应用服务器上
    • 只要您需要将这样的 bean 复制到多个节点中,您也需要它是可序列化的
    • 另一种可以省略序列化的情况是在 SE
    • 因此,您的 IDE 很聪明,不会强制要求 Serializable 在场

可序列化标记是 bean 的必需属性之一,它具有钝化能力(能够从活动状态转换为某种第二非活动状态)。如果 bean 具有钝化作用域(具有属性 passivating=true 的作用域),则它必须具有钝化能力。根据 CDI 规范 1.1。只有 SessionConversation 作用域是钝化作用域。

Chapter 6.6.4 Passivating scopes For example, the built-in session and conversation scopes defined in Section 6.7 are passivating scopes. No other built-in scopes are passivating scopes.

因此,您的会话 bean 需要具有钝化能力 - 因此需要可序列化,但您的应用程序范围的 bean 不需要。此外,某些 CDI 容器不会在部署期间在会话范围的 bean 上丢失 Serializable 时抛出错误,而只会在它们实际需要将 bean 实例从活动状态转移到被动状态时抛出错误(例如,实例限制已被取消)命中率、内存使用率等)

有关更多信息,请阅读 CDI 1.1 spec
快乐黑客