slf4j绑定logback源码解析
Logger log = LoggerFactory.getLogger(LogbackDemo.class);
如上述代码所示,在项目中通常会这样创建一个Logger对象去打印日志。
然后点进去,会走到LoggerFactory的getILoggerFactory()方法,如下代码所示。
public static ILoggerFactory getILoggerFactory() {
if (INITIALIZATION_STATE == UNINITIALIZED) {
synchronized (LoggerFactory.class) {
if (INITIALIZATION_STATE == UNINITIALIZED) {
INITIALIZATION_STATE = ONGOING_INITIALIZATION;
performInitialization();
}
}
}
switch (INITIALIZATION_STATE) {
case SUCCESSFUL_INITIALIZATION:
return StaticLoggerBinder.getSingleton().getLoggerFactory();
case NOP_FALLBACK_INITIALIZATION:
return NOP_FALLBACK_FACTORY;
case FAILED_INITIALIZATION:
throw new IllegalStateException(UNSUCCESSFUL_INIT_MSG);
case ONGOING_INITIALIZATION:
// support re-entrant behavior.
// See also http://jira.qos.ch/browse/SLF4J-97
return SUBST_FACTORY;
}
throw new IllegalStateException("Unreachable code");
}
performInitialization()方法表示执行初始化,点进去会调用到LoggerFactory的bind()方法,如下代码所示。
Set<URL> staticLoggerBinderPathSet = null;
if (!isAndroid()) {
// 查找org/slf4j/impl/StaticLoggerBinder.class这个类的路径
staticLoggerBinderPathSet = findPossibleStaticLoggerBinderPathSet();
// 如果有多个则打印Class path contains multiple SLF4J bindings
reportMultipleBindingAmbiguity(staticLoggerBinderPathSet);
}
// StaticLoggerBinder类是各个日志框架提供的,比如logback,如下图所示
StaticLoggerBinder.getSingleton();
INITIALIZATION_STATE = SUCCESSFUL_INITIALIZATION;
reportActualBinding(staticLoggerBinderPathSet);
fixSubstituteLoggers();
replayEvents();
// release all resources in SUBST_FACTORY
SUBST_FACTORY.clear();
StaticLoggerBinder类加载时会执行初始化,如下代码所示。
static {
SINGLETON.init();
}
void init() {
try {
try {
// 这里会完成logback的自动配置
new ContextInitializer(defaultLoggerContext).autoConfig();
} catch (JoranException je) {
Util.report("Failed to auto configure default logger context", je);
}
// logback-292
if (!StatusUtil.contextHasStatusListener(defaultLoggerContext)) {
StatusPrinter.printInCaseOfErrorsOrWarnings(defaultLoggerContext);
}
contextSelectorBinder.init(defaultLoggerContext, KEY);
initialized = true;
} catch (Exception t) { // see LOGBACK-1159
Util.report("Failed to instantiate [" + LoggerContext.class.getName() + "]", t);
}
}
logback源码解析
ContextInitializer.autoConfig()方法源码如下:
public void autoConfig() throws JoranException {
StatusListenerConfigHelper.installIfAsked(loggerContext);
// 查找配置文件,优先级:系统属性logback.configurationFile > logback-test.xml > logback.xml
URL url = findURLOfDefaultConfigurationFile(true);
if (url != null) {
configureByResource(url);
} else {
// 使用java的spi机制,查找Configurator的实现,如果有,则自动配置logback
Configurator c = EnvUtil.loadFromServiceLoader(Configurator.class);
if (c != null) {
try {
c.setContext(loggerContext);
c.configure(loggerContext);
} catch (Exception e) {
throw new LogbackException(String.format("Failed to initialize Configurator: %s using ServiceLoader", c != null ? c.getClass()
.getCanonicalName() : "null"), e);
}
} else {
// 使用默认的BasicConfigurator来自动配置logback
BasicConfigurator basicConfigurator = new BasicConfigurator();
basicConfigurator.setContext(loggerContext);
basicConfigurator.configure(loggerContext);
}
}
}