デフォルトのLoggerは優秀なのだが、
- メソッドの開始ログを出力するメソッドが欲しい
- リソースバンドルのキーを与えるとメッセージを取ってきてくれるメソッドが欲しい
といった拡張もしたくなる。
これまではLoggerクラスをラップして新しいクラスを作り、ラップクラスの中では、loggerを持っていて、処理をloggerに委譲してい
た。このやり方だと、getLoggerの引数にLoggerを使うクラスの完全修飾名を与えた場合、ラップクラスを使うクラスの数だけ、ラップクラスが
newされてしまう。
Loggerは内部でLogManagerとLoggerRepositoryを使って、作成したLoggerの重複を管理していると思うのだが、これをサブクラスで実装しても、
- Loggerでも管理してまーす
- ラップクラスでも管理してまーす
となって気持ちが悪い。
こういう場合は、継承してメソッドを拡張する。このサブクラスの作り方はlog4jのexamplesフォルダ内を参考にすればいい。
場所:logging-log4j-1.2.14\examples\subclass
LoggerFactoryを作る
このクラスでは、Loggerを拡張したクラス(サブクラス)をnewする実装を書く。Loggerはこのfactoryクラスを使ってLoggerを作る。
public class AppLoggerFactory implements LoggerFactory {
public AppLoggerFactory() {}
public Logger makeNewLoggerInstance(String name) {
return new AppLogger(name);
}
}
Loggerを継承したサブクラスを作る
ここには拡張するメソッドを記述する。あとはLogger.getLoggerメソッドで、上で作ったLoggerFactoryを渡せば完了。
public class AppLogger extends Logger {
private static final String FQCN = AppLogger.class.getName();
private static AppLoggerFactory factory = new AppLoggerFactory();
public AppLogger(String name){
super(name);
}
public static Logger getLogger(String name){
return (AppLogger) Logger.getLogger(name, factory);
}
public void startLog(String className, String methodName){
if(super.isDebugEnabled()){
super.log(FQCN, Level.DEBUG, className + "." + methodName, null);
}
}
}
Logger.getLoggerしたときにfacotryを与えることによって、LoggerはLogFactoryを使ってLoggerを作る。よってLoggerからAppLoggerにキャストできるオブジェクトを返してもらえる。
使ってみる
用意ができたので実際に使ってみる。使い方は簡単で、getLoggerして取得したオブジェクトを使うだけ。
AppLogger logger = AppLogger.getLogger("com.daipresents.test.logging.Log4jTest");
logger.startLog("Log4jTest", "main");
上記の例だとデバッグレベルで出力してくれる「startLogメソッド」が使えるようになる。