当前位置:  开发笔记 > 编程语言 > 正文

Log4J记录器应该声明为瞬态吗?

如何解决《Log4J记录器应该声明为瞬态吗?》经验,为你挑选了4个好方法。

我正在使用Java 1.4和Log4J.

我的一些代码涉及序列化和反序列化值对象(PO​​JO).

我的每个POJO都声明了一个记录器

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

序列化程序抱怨org.apache.log4j.Logger不是Serializable.

我应该用吗?

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

代替?



1> Aleksi Yrtti..:

如何使用静态记录器?或者您是否需要为每个类的实例提供不同的记录器参考?默认情况下,静态字段未序列化; 您可以使用ObjectStreamFieldnamed 的私有静态最终数组显式声明要序列化的字段serialPersistentFields.请参阅Oracle文档

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


静态记录器倾向于 - 除非你的应用程序被非常仔细地编码 - 保持类加载器,以便它们不能被垃圾收集.这显示了例如在maven构建期间稳定增加的内存使用量,当javac由maven分叉时消失.
静态记录器不适合重新部署Web应用程序.

2> mindas..:

记录器必须是静态的; 这会使它不可序列化.

除非你有充分的理由这样做,否则没有理由让logger成为非静态的.


*"没有理由让记录器非静态,除非你有充分的理由这样做."* - 这让我的头爆炸了!;-)
如果要为每个实例使用不同的记录器名称(例如,在记录器名称的末尾附加实例唯一字符串),或者如果在超类对象中有记录器,则有时可以使用非静态记录器.并且您希望它使用子类实例的名称.

3> John Meagher..:

如果您真的想要采用瞬态方法,则需要在反序列化对象时重置日志.这样做的方法是实现该方法:

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

Serializable的javadoc 有关于此方法的信息.

您的实现将类似于:

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

如果不这样做,则在反序列化对象后,log将为null.



4> user9189..:

将记录器字段声明为静态或瞬态.

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

通常记录器字段被声明为静态,但是如果您需要它是一个实例字段,则只需将其声明为瞬态,因为它通常用于任何非可序列化字段.在反序列化时,logger字段将为null,因此您必须实现readObject()方法以正确初始化它.

推荐阅读
夏晶阳--艺术
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有