あなたのコメントは、「冗長」はすべてのクラスでこのコード行を繰り返す必要性を指すと述べています。私の最初の応答は、全体像で、すべてのクラスに2行のコード(変数定義とインポートステートメント)を追加することはそれほど大きな問題ではないということです。特に、振る舞いを持ち、したがってロギングを行う必要があるクラスにそれらを追加する必要があるだけです。とはいえ、使用している特定のコード行では、コピーアンドペーストエラーが発生する傾向があります(これについては後で詳しく説明します)。
ただし、代替手段が必要なため、以下にいくつか示します。理由は、それらを使用する場合と使用しない場合があります。
アプリ全体に単一のロガーを使用する
どのクラスがレポートしているのかを気にしない場合、または必要なすべてのコンテキストをメッセージに入れても構わない場合は、単純なシングルトンロガーが機能します。
LoggerSingleton.getInstance().debug("MyController is running")
私の意見では、ロギングフレームワークの大きな利点の1つは、ログメッセージを別の宛先に送信する場合のみ、別のロガーインスタンスによってコンテキストが提供されることです。1行のコードを保存するためだけにそれをあきらめることはしません(まだインポートが必要です)。
さらに、これにより、使用する時点での冗長性が向上し、キーストロークがはるかに多くなります。
使用時にロガーを作成する
変数を削除するという理由だけで、これを捨てています。私はそれにコメントする必要はないと思います。それはロガーインスタンスを取得するための私の好ましいテクニックを示していますが。
Logger.getLogger(getClass()).debug("blah blah blah");
Beanポストプロセッサを使用してロガーを挿入する
例ではSpringを使用しており、Springを使用すると、Bean初期化コードにフックできます。logger
メンバー変数のBeanを検査し、Logger
見つかったときにインスタンスを作成するポストプロセッサーを作成できます。
このようなポストプロセッサは数十行のコードにすぎませんが、これはアプリケーションのもう1つの重要な部分であり、そのためバグの別の潜在的な原因となります。私はそれらをできるだけ少なくすることを好みます。
ミックスインを使用する
ScalaとGroovyは、動作をカプセル化できる特性を提供します。典型的なScalaパターンは、Logging
トレイトを作成し、ロギングが必要なクラスに追加することです。
class MyController with Logging
残念ながら、これは言語を切り替える必要があることを意味します。Java 8を使用していない限りLogging
、「デフォルトのメソッド」でインターフェースを作成できます。
public interface Logging {
default Logger getLogger() {
return Logger.getLogger(getClass());
}
}
今、あなたのクラスコード内で、あなたは単に使うことができます
getLogger().debug("blah blah blah");
これは簡単ですが、いくつかの欠点があります。1つには、すべてのインターフェイスメソッドがパブリックであるため、それを使用するすべてのクラスのインターフェイスを汚染します。特にインターフェース/実装の分離に従う場合は、Springによってインスタンス化および注入されるクラスにのみ使用する場合は、おそらくそれほど悪くはありません。
より大きな問題は、すべての呼び出しで実際のロガーインスタンスを検索する必要があることです。高速ですが不要です。
そして、まだimportステートメントが必要です。
ロガーをスーパークラスに移動する
繰り返します。繰り返しロガー定義が冗長になることはありませんが、そうであれば、これを排除するための最良のアプローチだと思います。
public abstract class AbstractController {
protected Logger logger = Logger.getLogger(getClass());
}
これで、コントローラークラスはから継承されAbstractController
、logger
変数にアクセスできます。@Controller
具象クラスに注釈を付ける必要があることに注意してください。
一部の人々はこれを継承の倒錯だと思うでしょう。私は、クラスAbstractController
ではなくクラスに名前を付けることで、それらを軟化させようとしましたAbstractProjectClass
。is-a関係があるかどうかを自分で決めることができます。
他の人々は、静的変数ではなくインスタンス変数の使用に反対します。IMO静的ロガーは、クラス名を明示的に参照する必要があるため、コピーアンドペーストエラーが発生しやすくなります。getClass()
ロガーが常に正しいことを確認します。
getLogger()
取得するロガーの名前を通知する必要があります。