代码之家  ›  专栏  ›  技术社区  ›  Vihung

日志4J记录器是否应声明为瞬态?

  •  30
  • Vihung  · 技术社区  · 17 年前

    我使用的是带有Log4J的Java 1.4。

    我的一些代码涉及序列化和反序列化值对象(POJO)。

    我的每一个pojos都用

    private final Logger log = Logger.getLogger(getClass());
    

    序列化程序抱怨org.apache.log4j.logger不可序列化。

    我应该用吗?

    private final transient Logger log = Logger.getLogger(getClass());
    

    相反?

    9 回复  |  直到 17 年前
        1
  •  26
  •   PhilippeLM david a.    14 年前

    使用静态记录器怎么样?或者,对于类的每个实例,您是否需要不同的记录器引用?默认情况下,静态字段不序列化;您可以显式声明要用的私有、静态、最终数组序列化的字段。 ObjectStreamField 命名 serialPersistentFields . See Oracle documentation

    新增内容: 当你使用 getLogger(getClass()) ,您将在每个实例中使用相同的记录器。如果要对每个实例使用单独的记录器,则必须在getlogger()-方法中区分记录器的名称。例如getLogger(getClass().getName()+hashCode())。然后,您应该使用transient属性来确保记录器没有被序列化。

        2
  •  11
  •   mindas    17 年前

    记录器必须是静态的;这将使其不可序列化。

    没有理由使记录器非静态,除非您有充分的理由这样做。

        3
  •  9
  •   Yishai    15 年前

    如果你 真的? 如果要使用临时方法,则在反序列化对象时需要重置日志。实现方法是:

     private void readObject(java.io.ObjectInputStream in) 
       throws IOException, ClassNotFoundException;
    

    用于 Serializable 有关于此方法的信息。

    您对它的实现如下所示:

     private void readObject(java.io.ObjectInputStream in) 
         throws IOException, ClassNotFoundException {
       log = Logger.getLogger(...);
       in.defaultReadObject();
     }
    

    如果不这样做,则在反序列化对象后,日志将为空。

        4
  •  5
  •   user9189    17 年前

    要么将记录器字段声明为静态字段,要么声明为瞬态字段。

    这两种方法都确保writeObject()方法不会在序列化期间尝试将字段写入输出流。

    通常,记录器字段被声明为静态的,但是如果您需要它是一个实例字段,只需声明它是暂时的,就像它通常用于任何不可序列化的字段一样。但是,在反序列化之后,logger字段将为空,因此必须实现readObject()方法才能正确初始化它。

        5
  •  2
  •   Philip Helger    17 年前

    尝试将记录器设置为静态。而不必担心序列化,因为它是由类加载器处理的。

        6
  •  2
  •   Alhazred    17 年前

    这些类型的情况,特别是在EJB中,通常最好通过线程本地状态来处理。通常,用例类似于遇到问题的特定事务,您需要将日志提升为该操作的调试,以便生成有关问题操作的详细日志。在事务中携带一些线程本地状态,并使用它来选择正确的记录器。坦率地说,我不知道在这个环境中,在何处设置实例的级别是有益的,因为将实例映射到事务中应该是一个容器级别的函数,您实际上无法控制给定事务中使用的实例。

    即使在处理DTO的情况下,通常也不建议将系统设计成需要特定实例的方式,因为设计可以很容易地以使其成为错误选择的方式发展。从现在起一个月后,您可以决定效率考虑因素(缓存或其他改变生命周期的优化)将打破将实例映射到工作单元的假设。

        7
  •  0
  •   MB.    17 年前

    如果您希望记录器是每个实例的,那么是的,如果您要序列化对象,那么您将希望使它成为暂时的。log4j记录器是不可序列化的,不在我使用的log4j版本中,因此,如果不使记录器字段成为临时字段,则在序列化时会得到异常。

        8
  •  0
  •   Glever    17 年前

    记录器不可序列化,因此在实例字段中存储时必须使用瞬态。 如果要在反序列化之后恢复记录器,可以存储对对象进行反序列化的级别(字符串)。

        9
  •  0
  •   James A. N. Stauffer    17 年前

    有充分的理由使用实例记录器。一个非常好的用例是,您可以在一个超级类中声明记录器,并在所有的子类中使用它(唯一的缺点是,来自超级类的日志被归于子类,但通常很容易看到)。

    (和其他人提到的一样,使用静态或瞬态)。