31

Log4JでJava1.4を使用しています。

私のコードの中には、値オブジェクト(POJO)のシリアル化と逆シリアル化が含まれているものがあります。

私の各POJOは、

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

シリアライザーは、org.apache.log4j.Loggerがシリアライズ可能ではないと文句を言います。

使用する必要があります

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

代わりは?

4

9 に答える 9

27

静的ロガーを使用するのはどうですか?または、クラスのインスタンスごとに異なるロガー参照が必要ですか?静的フィールドはデフォルトではシリアル化されません。ObjectStreamField名前付きのプライベート、静的、最終配列を使用してシリアル化するフィールドを明示的に宣言できますserialPersistentFieldsOracleのドキュメントを参照してください

追加されたコンテンツ:getLogger(getClass())を使用すると、各インスタンスで同じロガーが使用されます。インスタンスごとに個別のロガーを使用する場合は、getLogger()メソッドでロガーの名前を区別する必要があります。例:getLogger(getClass()。getName()+ hashCode())。次に、transient属性を使用して、ロガーがシリアル化されていないことを確認する必要があります。

于 2008-09-17T11:20:52.340 に答える
11

ロガーは静的である必要があります。これにより、シリアル化できなくなります。

強い理由がない限り、ロガーを非静的にする理由はありません。

于 2008-09-17T11:20:25.883 に答える
9

本当に一時的なアプローチを取りたい場合は、オブジェクトが逆シリアル化されたときにログをリセットする必要があります。その方法は、次のメソッドを実装することです。

 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();
 }

これを行わないと、オブジェクトを逆シリアル化した後にログが null になります。

于 2008-09-17T12:27:37.923 に答える
5

ロガー フィールドを静的または一時的として宣言します。

どちらの方法でも、シリアル化中に writeObject() メソッドがフィールドを出力ストリームに書き込もうとしないようにします。

通常、ロガー フィールドは静的であると宣言されますが、インスタンス フィールドにする必要がある場合は、シリアル化できないフィールドに対して通常行われるように、一時的であると宣言するだけです。ただし、逆シリアル化すると、ロガー フィールドは null になるため、適切に初期化するには readObject() メソッドを実装する必要があります。

于 2008-09-17T12:26:37.113 に答える
2

代わりに、ロガーを静的にしてみてください。クラスローダーによって処理されるため、シリアル化について気にする必要はありません。

于 2008-09-17T11:21:36.940 に答える
2

この種のケースは、特に EJB では、通常、スレッド ローカル状態を介して処理するのが最適です。通常、ユースケースは、問題が発生している特定のトランザクションがあり、その操作のログをデバッグに昇格させて、問題のある操作に関する詳細なログを生成できるようにする必要があるようなものです。トランザクション全体でスレッド ローカル状態を保持し、それを使用して正しいロガーを選択します。率直に言って、トランザクションへのインスタンスのマッピングはコンテナー レベルの関数である必要があるため、この環境で INSTANCE のレベルを設定することが有益な場所はわかりません。実際には、インスタンスで使用されるインスタンスを制御することはできません。とにかく与えられたトランザクション。

DTO を扱っている場合でも、特定のインスタンスが必要になるような方法でシステムを設計することは、一般的には良い考えではありません。今から 1 か月後に、インスタンスを作業単位にマッピングするという想定を破る効率の考慮事項 (キャッシングまたはその他のライフサイクルを変更する最適化) を決定することができます。

于 2008-09-17T12:26:34.023 に答える
0

ロガーをインスタンスごとに設定したい場合は、そうです。オブジェクトをシリアル化する場合は、ロガーを一時的にする必要があります。Log4Jロガーはシリアル化できません。とにかく私が使用しているLog4Jのバージョンではないため、ロガーフィールドを一時的にしないと、シリアル化で例外が発生します。

于 2008-09-17T11:48:22.837 に答える
0

ロガーはシリアル化できないため、インスタンスフィールドに格納するときはtransientを使用する必要があります。逆シリアル化後にロガーを復元する場合は、シリアル化されるオブジェクトを示すレベル(文字列)を保存できます。

于 2008-09-17T11:54:18.283 に答える
0

インスタンスロガーを使用する正当な理由があります。非常に良い使用例の 1 つは、ロガーをスーパークラスで宣言し、それをすべてのサブクラスで使用できるようにすることです (唯一の欠点は、スーパークラスからのログがサブクラスに起因することですが、通常は簡単にそれを参照してください)。

(他の人が言及したように、静的または一時的な使用を使用します)。

于 2008-09-17T15:02:56.067 に答える