簡體   English   中英

Log4J記錄器應該聲明為瞬態嗎?

[英]Should a Log4J logger be declared as transient?

我正在使用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());

代替?

如何使用靜態記錄器? 或者您是否需要為每個類的實例提供不同的記錄器參考? 默認情況下,靜態字段未序列化; 您可以使用名為serialPersistentFieldsObjectStreamField的私有靜態最終數組顯式聲明要序列化的字段。 請參閱Oracle文檔

添加內容:當您使用getLogger(getClass())時 ,您將在每個實例中使用相同的記錄器。 如果要為每個實例使用單獨的記錄器,則必須在getLogger() - 方法中區分記錄器的名稱。 例如getLogger(getClass()。getName()+ hashCode())。 然后,您應該使用transient屬性來確保記錄器未序列化。

記錄器必須是靜態的; 這會使它不可序列化。

除非你有充分的理由這樣做,否則沒有理由讓logger成為非靜態的。

如果您真的想要采用瞬態方法,則需要在反序列化對象時重置日志。 這樣做的方法是實現該方法:

 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。

將記錄器字段聲明為靜態或瞬態。

兩種方式都確保writeObject()方法在序列化期間不會嘗試將字段寫入輸出流。

通常記錄器字段被聲明為靜態,但是如果您需要它作為實例字段,則只需將其聲明為瞬態,因為它通常用於任何非可序列化字段。 在反序列化時,logger字段將為null,因此您必須實現readObject()方法以正確初始化它。

嘗試使Logger靜態。 你不必關心序列化,因為它是由類加載器處理的。

這些情況,特別是在EJB中,通常最好通過線程本地狀態來處理。 通常,用例就像您有一個特定的事務遇到問題而需要將日志提升到該操作的調試,這樣您就可以生成詳細的問題操作日志。 在整個事務中攜帶一些線程本地狀態,並使用它來選擇正確的記錄器。 坦率地說,我不知道在這個環境中在INSTANCE上設置級別會有什么好處,因為實例到事務的映射應該是一個容器級別的函數,你實際上無法控制在一個實例中使用哪個實例。無論如何都給了交易。

即使在您處理DTO的情況下,通常也不應該以需要給定特定實例的方式設計系統,因為設計很容易以一種不好的方式發展。 您可以從現在開始一個月,並確定效率考慮因素(緩存或其他一些生命周期更改優化)將打破您關於將實例映射到工作單元的假設。

如果您希望Logger是按實例進行的,那么您可能希望在要序列化對象時使其成為瞬態。 Log4J記錄器不是可序列化的,不是我正在使用的Log4J版本,所以如果你不使你的Logger字段瞬態,你將獲得序列化的例外。

記錄器不可序列化,因此在將它們存儲在實例字段中時必須使用瞬態。 如果要在反序列化后恢復記錄器,可以存儲您的對象的Level(String),並將其序列化。

有充分的理由使用實例記錄器。 一個非常好的用例是你可以在超類中聲明記錄器並在所有子類中使用它(唯一的缺點是來自超類的日志歸因於子類,但它通常很容易看到了)。

(像其他人提到的那樣使用靜態或瞬態)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM