■SpringMVC の小径 ちょっと寄り道 ロギングの小径 |
9-3)log4j2 ログクラスの実装 |
Log4j2を利用するためには、まずLog4j2のプラグインが必要になりますが、 これは当然、Mavenさんにとって来てもらうつもりなので、pom.xmlに記述します。 「1-3)pom.xmlの編集」で定義した pom.xmlを確認すると、 おや!既に定義されてましたね!!(あんたはエライ!) ということで、プラグインの事は気にしないで先に進みましょう。 Log4j2についてネットで検索すると、色々なサイトで実際のサンプルソースコードが紹介されています。 その中でも、代表的なものとして以下のようなソースコードを良く見かけます。 package jp.co.hoge.log; import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.LogManager; public class MyClass { //Loggerを取得 private static Logger logger = LogManager.getLogger(MyClass.class); public static void main(String[] args) { try { //情報を出力 logger.info("running {}", MyClass.getSimpleName()); } catch(Exception e) { //エラー情報を出力 logger.error("exception {}", e.getMessage()); } } } 上のソースコードは、確かに非の打ち所のない素晴らしいお手本のコードだと私も思います。 では、ほんとにこれをそのまま実際のアプリケーションで使っているの? と、問われれば、答えは「いいえ」です。 正直言って、上のようなソースコードを紹介しているサイトの製作者(Log4j2を知り尽くしている人)が こんなソースコードを実際の業務で書いているとは到底思えません。 理由1:private static Logger logger 宣言を各クラスごとに指定しないといけないのは、ダサい。 理由2:LogManager.getLogger(MyClass.class); getLoggerの引数をクラス名固定で指定しているので汎用性がない。(コピペできないのよ) 理由3:LogManagerメソッドの第一引数にある "{}"は、log4j2の特殊な意味を持つ文字列なので こんなlog4j2事情を、アプリケーションレイヤーのソースコードにベタベタと 直書きするのは好ましくない(個人的には) 等々の事情により、上のソースコードは、あくまで教科書であって実戦ではあまり使いたくないコードです。 んな偉そうなこと言うなら、じゃぁ、ホントの実戦的なコードというのを見せてみろや!!。 と仰るのは当然の事。 そういうLog4j2マスターなホントにえらい人達がどんな実戦的ソースコード書いているか見たことはないので あくまで私の個人的産物ですが、いつも私が実装しているソースコードをご紹介しておきます。 私のばやいは、ログ出力するための専用のクラス(MyLog4J.java)を一つ贅沢に作ってしまいます。 |
src/main/java/jp/dip/arimodoki/common/MyLog4J.java 何も隠し事はしません。一糸まとわぬ裸の私を全て見てください(きゃ♥) 説明はソースコードのコメントに書いてあります。 もし使いたかったら自由に使ってください。 これで先ほどのサンプルソースコードを置き換えると package jp.co.hoge.log; import jp.dip.arimodoki.common.MyLog4J; public class MyClass { //Loggerを取得 private MyLog4J logger = MyLog4J.getInstance(); public static void main(String[] args) { try { //情報を出力 logger.log_info(this, "running [" + MyClass.getSimpleName() + ”]"); } catch(Exception e) { //エラー情報を出力 logger.log_error(e); } } } |
となり、最初よりは少しだけシンプルになりました。 偉そうな事言うた割には大したことないなぁワレェ!! はい、すみませんねぇ。 じゃあちょっとだけ隠し味をふりかけます。 アプリケーションを開発するときは、だいたい共通の定数とかがあって、 それらを全部まとめたインターフェースとかよく作りますよね。 具体例) package jp.dip.arimodoki.common; /** * アプリケーション共通の定数などを宣言するインターフェースです。 */ public interface CConst { public static final String NANTYARA_TEISU = "なんちゃらな定数"; } これに、隠し味として次の1行(赤字)を追加します。 package jp.dip.arimodoki.common; /** * アプリケーション共通の定数などを宣言するインターフェースです。 */ public interface CConst { public static MyLog4J logger = MyLog4J.getInstance(); public static final String NANTYARA_TEISU = "なんちゃらな定数"; } これで先ほどのサンプルソースコードを再度置き換えると、今度はスパイスが効いてるので、 package jp.co.hoge.log; import jp.dip.arimodoki.common.CConst; public class MyClass implements CConst{ public static void main(String[] args) { try { //情報を出力 logger.log_info(this, "running [" + MyClass.getSimpleName() + ”]"); } catch(Exception e) { //エラー情報を出力 logger.log_error(e); } } } みたいに、クラスに対してCConstをimplementsしてあげれば どのクラスでもいちいちloggerクラスの変数宣言が必要なくなり、だいぶすっきりします。 ログ出力メソッド自体はこれ以上隠しようがありませんが、これはどの方法でも仕方がないので諦めます。 人によっては、loggerの宣言が見えなくてわかりにくいと思う人もいると思いますが、 そういう人は、最初のprivate MyLog4J logger = MyLog4J.getInstance();宣言方式を使うようにすれば 気にならないと思います。 だいぶいい感じやんけ?もらっとこ。 そやけど、log_info()はしゃーないけど、 log_error()は、いちいち try {} catch() {} せなアカンし、いちいち面倒やのぅ? そーですね確かに。それでは最後の寄り道。Aspectの魔法を ちちんぷいぷい してみましょうか。 続く。 (ところで、なんで関西弁?) |
9-2)log4j2 設定ファイル ![]() |
9-3)log4j2 ログクラスの実装 |
![]() |