又一次对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;
原创文章,作者:ItWorker,如若转载,请注明出处:https://blog.ytso.com/tech/pnotes/115613.html