Java:何时序列化非序列化对象或将它们置于瞬态?

时间:2014-03-06 12:23:50

标签: java serialization

我对新系列中的非序列化字段,序列化对象中的对象感到困惑 什么应序列化或什么应标记为瞬态序列化?

以下是一个例子:

@Stateless
public class NonSerializedThingStateless{
...
}

@RequestScoped
public class NonSerializedThingRequestScoped{
...
}


@Named
@SessionScoped
public class SerializedBean implements Serializable{
  @Inject
  private NonSerializedThingRequestScoped nstrs;

  @Inject
  private NonSerializedThingStateless nsts;

  private List<Something> list; //or something else like POJO

  ...
}

有什么好的,简单的方法,我可以告诉我何时应该序列化注入或使用的类或指南?

我是否必须在序列化和将事物置于瞬态之间做出选择,还是有其他方式?

2 个答案:

答案 0 :(得分:2)

首先,警告:您可能只想在简单情况下使用@Inject(通常是单身人士)。对于其他一切,自动装配可以工作,但它可以非常快速地混淆。

也就是说,transient的规则很简单:当您读取对象(反序列化)时,您是否还需要一切来重新创建原始状态?

如果一个对象依赖于当前请求,那么答案可能是:在从流中读取bean时,请求将很快消失。

答案 1 :(得分:1)

在Web应用程序中,会话范围的变量通常会声明为implements Serializable。这有几个常见的原因:

  1. 可以为会话复制配置群集环境(运行Web应用程序的应用服务器不止一个)。在这种情况下,当用户会话被更改时(例如,我将项目添加到我的购物车),该更改将被推送到群集中的所有其他应用服务器。这些应用程序服务器在不同的JVM中运行,需要一种将Java对象从一个JVM传递到另一个JVM的方法。为此,他们将会话序列化为字节流并将字节写入套接字。
  2. 当单个应用服务器关闭时(可能已部署新的Web应用程序版本),可以将其配置为保留会话,这意味着它通常会将会话写入磁盘。当它再次启动时,会从磁盘读取会话并在正在运行的Web应用程序中重新创建。再次执行此操作,会话将序列化为byte[]并写入文件系统。
  3. 在决定是否应该序列化字段或transient时,请考虑以上两个示例。如果我们这样做,那么有一些简单的规则。一般为:

    1. 任何请求作用域应该transient。例如,用户在搜索字段中键入的搜索文本。这些信息实际上不需要保留,因为它只与当前请求相关。
    2. 任何无国籍人都应该transient。这里的经典示例是记录器。记录器不需要序列化,因为没有应该保存的状态。如果创建了新的记录器,代码将继续正常运行!
    3. 任何会话作用域都应序列化。例如,用户首选项或添加到购物车的商品。
    4. 所以回答你的问题:

      有什么好的,简单的方法可以判断我应该在何时序列化注入或使用的类或指南?

      考虑为什么会话被序列化(即我上面写的内容)并确定序列化是否有意义,无论是否注入了字段。

      是否我必须在序列化和将事物置于瞬态之间做出选择,还是有其他方式?

      如果你肯定要序列化会话;然后是的,你必须选择应该序列化的内容和什么应该是瞬态的。 但是,如果您没有在群集环境中运行,则不会在关机时将会话保存到磁盘,并且没有其他问题;然后,不进行任何Serializable是完全合理的,因为不会发生序列化!