せっかくなので、ApacheのCommons Loggingを通してlog4jを使ってみます。
設定
1. まずlog4j.jarをWebContent/WEB-INF/libにコピペします。(commons-logging.jarはstruts-blankをインポートすれば最初からWebContent/WEB-INF/libに入っています。)最初$CATALINA_BASE/libに入れていたのですが、特定のアプリケーションからのみ参照できるようにしたい場合は、WEB-INF/libに入れるのが慣例のようです。
Eclipseを使ってる場合はBuild Pathからライブラリ追加しても使えないので注意してください。Tomcatが参照できる場所に置かないといけません。
2. log4j.xmlをsrcに置きます。
3. commons-logging.propertiesをsrcに置きます。中身は、
org.apache.commons.logging.Log=org.apache.commons.logging.impl.Log4JLoggerとします。
動作確認
簡単に確認できればいいので、生成したloggerのクラス名を表示するアクションクラスを作りました。
[TestAction.java]
public class TestAction extends Action { @Override public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { Log logger = LogFactory.getLog(TestAction.class); System.out.println(logger.getClass()); return null; } }[実行結果]
[INFO ] 2013-01-27 00:01:50 org.apache.struts.chain.ComposableRequestProcessor::init() - Initializing composable request processor for module prefix '' [INFO ] 2013-01-27 00:01:50 org.apache.struts.chain.commands.servlet.CreateAction::createAction() - Initialize action of type: main.TestAction class org.apache.commons.logging.impl.Log4JLogger
お、Log4JLoggerクラスのloggerインスタンスが生成できているようです。
strutsの内部のロギングもlog4jになってる。。log4j.xmlで別のlogger定義した方がよさそうですね。
仕組み
とりあえずソース読んだり、デバッグ実行したりして理解したことです。- Jdk14Loggerはadapterの役割を果たし、log4jのロガーをcommons-loggingLogインターフェースで扱えるようにする。
- LogFactoryインターフェースを継承したlog4j専用のファクトリーを作成することで、log4jのロガーを取り出せるようにする。これは、Abstract Factory patternですかね。
- と思いきや、log4jのファクトリであるLog4jFactoryは@depricatedになっている。結局ファクトリクラスはLogFactoryImplしかなくて、ここで使用するログを切り替える処理が入っている。
- LogFactoryImpl#newInstanceFactoryでプロパティファイルから使用するロガーのクラス名を取得。このクラス名を元に使いたいロガーのクラスをクラスローダにあげて、リフレクションでコンストラクタとってきて、・・っていう処理を行う。
デザインパターン勉強してたおかげで、やりたいことはスッと入ってきた。クラスローダの仕組みがいまいち分かってないから勉強したい。