はじめに
JavaでLogを出力際には、Log4jやLogbackなどのライブラリを使ったりjava.util.loggingを使ったりします。どのライブラリ・APIでも大抵は以下のようにLoggerインスタンスを取得・生成します。
Logger logger = Logger.getLogger(Hoge.class);
すべてのクラスでこれらを書いていくのは面倒です。
Springを使ってもうちょっとシンプルに書く方法を探してみましょう。
元ネタ
ほぼ、このサイトの実装の紹介です。
http://memorynotfound.com/spring-inject-logger-annotation-example/
ありとうございます。
SpringによるLoggerのInjection
Springを使っている場合、以下のようにアノテーションが付いているfiledに対してLoggerをInjectionすることができます。
@Log
private static Logger logger;
記述量は少しですがへりましたし、引数のクラスを明示しなくてもよくなることでLoggerのミス(コピペで時々あるはずです)をなくすることができます。
いかに実装方法を説明していきます。
Logアノテーション
以下のようにLogアノテーションを作成します。
@Retention(RUNTIME)
@Target(FIELD)
@Documented
public @interface Log {
}
ランタイムで参照するので@Retention(RUNTIME)
、対象はフィールドなので@Target(FIELD)
とします。
LogInjector
Springをつかって、先ほど作成した@Log
アノテーションが付与されたフィールドに、LoggerをInjectionするコードを書きます。
以下のようにSpringのBeanPostProcessor実装を作成し、その中でLoggerを作成します。
@Component
public class LogInjector implements BeanPostProcessor {
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
@Override
public Object postProcessBeforeInitialization(final Object bean, String name) throws BeansException {
ReflectionUtils.doWithFields(bean.getClass(), new ReflectionUtils.FieldCallback() {
public void doWith(Field field) throws IllegalArgumentException, IllegalAccessException {
// make the field accessible if defined private
ReflectionUtils.makeAccessible(field);
if (field.getAnnotation(Log.class) != null) {
Logger log = Logger.getLogger(bean.getClass());
field.set(bean, log);
}
}
});
return bean;
}
}
使用方法
これで準備は整いました。あとは以下の手順で使えるようになります。
- LogInjectorをSpring管理下におく。
- LoggerをInjectionしたいクラスのstatic filedに
@Log
を付与する。
これで毎回 getLogger
しなくて済むようになりました。