1. 程式人生 > >用SLF4J和Guidce記錄日誌

用SLF4J和Guidce記錄日誌

又一次對java.util.logger無語的時候,我在想如何用SLF4J logger取代它。儘管Guice針對java.util.logger提供一個非常好的內部繫結,slf4j提供一個更好的語法。永遠是細節中的魔鬼…如果你想你的logger與當前類一起初始化,你不能簡單地注入logger。但是,在Guice中有一個好教程(http://code.google.com/p/google-guice/wiki/CustomInjections):關於注入log4j looger。SLF4J也是這樣工作的。

首先你需要一個新的註解,像這樣注入InjectLogger:

import static java.lang.annotation.ElementType.FIELD;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target; 
@Target({FIELD}) @Retention(RetentionPolicy.RUNTIME)

public @interface InjectLogger { }

然後是一個TypeListener,用註解InjectLogger監聽org.slf4j.Logger類。

import java.lang.reflect.Field;
import org.slf4j.Logger;
import com.google.inject.TypeLiteral;
import com.google.inject.spi.TypeEncounter;
import com.google.inject.spi.TypeListener;
public class Slf4jTypeListener implements TypeListener {
    public <I> void hear(TypeLiteral<I> aTypeLiteral,
         TypeEncounter<I> aTypeEncounter) {
         for (Field field : aTypeLiteral.getRawType().getDeclaredFields()) {
                if (field.getType() == Logger.class &&
                        field.isAnnotationPresent(InjectLogger.class)) {
                        aTypeEncounter.register(new Slf4jMembersInjector<I>(field));
                }
        }
  }
} 

最後,需要Slf4jMembersInjector(Slf4j 成員注入),做實際注入:

import java.lang.reflect.Field;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.inject.MembersInjector;
public class Slf4jMembersInjector<T> implements MembersInjector<T> {
    private final Field field;
    private final Logger logger;
    Slf4jMembersInjector(Field aField) {
      field = aField;
      logger = LoggerFactory.getLogger(field.getDeclaringClass());
       field.setAccessible(true);
    }
    public void injectMembers(T anArg0) {
       try {
        field.set(anArg0, logger);
      } catch (IllegalAccessException e) {
        throw new RuntimeException(e);
      }
    }
} 

現在只需要在模組類內部繫結TypeListener:

bindListener(Matchers.any(), new Slf4jTypeListener());

實際應用是簡單的,但是我們需要用@InjectLogger而不是@Inject.

@InjectLogger Logger logger;