倭マン's BLOG

くだらない日々の日記書いてます。 たまにプログラミング関連の記事書いてます。 書いてます。

commons-logging 基礎の基礎

commons-logging とは?

commons-logging とは、Apache Jakarta Project で開発されているロギング・コンポーネントです。 実際には、commons-logging 自体がログを記録するわけではなく、ロギングのための汎用インターフェースを提供して、その処理を他の実装ライブラリに委譲します。

使い方

commons-logging の使い方は簡単です。

(1) Log オブジェクトを取得する。
(2) Log オブジェクトのメソッドを使ってログを記録する。

(1) まずは準備として、LogFactory オブジェクトを使用して Log オブジェクトを取得します:

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; 

class SomeClass{

    /** Log オブジェクトを取得する。 */
    private static final Log LOG = LogFactory.get(SomeClass.class);

    // ・・・
}

LogFactory#get() メソッドには引数として Class オブジェクト(通常、その Log オブジェクトを使用するオブジェクトのクラス)を渡します。 また、Log オブジェクトは大抵の場合、static フィールドとして宣言します*1

(2) 次にそのクラスのメソッド内で Log オブジェクトのログ記録メソッドを呼び出して、ログを記録します(ログ記録メソッドの一覧は次節):

class SomeClass{

    private static final Log LOG = LogFactory.get(SomeClass.class);

    /** 2. メソッド内で Log オブジェクトのメソッドを
       *     呼び出してログを記録する。
       */
    public void invokeMethod(){
        LOG.info("start : SomeClass.invokeMethod()");

        //  何らかの処理

        LOG.info("end: SomeClass.invokeMethod()");
    }
}

メソッドには、メッセージを表す Object オブジェクトを引数にとるメソッドと、そのメッセージに加えて例外も引数にとるメソッドがあります:

  • void info(Object msg);
  • void info(Object msg, Throwable ex); など

これらのログ記録メソッドは、コードガード(code guard)メソッドと共に用いることが推奨されています*2。 これらのメソッドの使い方は以下の通り(コードガード・メソッドの一覧は次節):

/* メソッド内 */
if(LOG.isInfoEnabled())
    LOG.info("start : SomeClass.invokeMethod()");

ログ記録メソッド & コードガード・メソッド

ログ記録用のメソッドは以下の6つが定義されています:

メソッド 内容 使用目安 コンソール出力 コードガード・メソッド
fatal 致命的エラー 致命的なエラーにより、プログラムが即停止すべき程度のエラーが発生したとき Yes isFatalEnabled()
error エラー fatal でない実行時のエラー、予期されていない状態に陥ったとき Yes isErrorEnabled()
warn 警告 非推奨な API を使用したなどの、好ましくない状況、状態に陥ったとき Yes isWarnEnabled()
info 情報 関心のある何らかのイベントが発生したとき Yes isInfoEnabled()
debug デバッグ システムの処理の流れを記録するとき No isDebugEnabled()
trace トレース システムの細かな流れの情報を記録するとき No isTraceEnabled()

実装の選択

commons-logging は「ロギングのための汎用インターフェース」なので、実際にログ出力を行う実装は設定によって変更することが出来ます(プログラム実行中には無理ですが)。 また、指定をしない場合は、実行環境によって適切な実装を自動的に検出してくれます。

Log クラスの実装の検出手順は以下の通り:

  1. クラスパス内に commons-logging.properties ファイルがあれば、そこに設定されている org.apache.commons.logging.Log (もしくは org.apache.commons.logging.log) の値で指定されているクラス名の Log クラスを使用します。
  2. システム・プロパティ org.apache.commons.logging.Log (もしくは org.apache.commons.logging.log) が設定されていれば、その値で指定されるクラス名の Log クラスを使用します。
  3. Log4j ライブラリがクラスパス内で見つかれば、Log4j を使用します。
  4. Java 実行環境が1.4以降なら、JDK 付属のロギング API を使用します。
  5. SimpleLog を使用する。

Maven2 では

Log4j が自動的にダウンロードされるので、特に指定しない限り Log4j が使用されます。 なのに、servlet-api.jar, logkit.jar, avalon-framework.jar なども自動的にダウンロードされてしまうのはいかがなものか・・・ どれも数十 KB 程度なんで大した問題じゃないけど。

*1:J2EE コンテナなどの ClassLoader を考慮しなくてはいけない環境では、static として宣言するとマズイ場合もアリ。

*2:主にパフォーマンスの観点から。 サポートされていないログ記録メソッドを呼び出さないようにするため。