首页 > 其他分享 >LoggerFactory.getLogger 的过程(一)

LoggerFactory.getLogger 的过程(一)

时间:2022-11-14 11:02:47浏览次数:45  
标签:StaticLoggerBinder INITIALIZATION slf4j getLogger STATE static LoggerFactory 过程

Logger log = LoggerFactory.getLogger(TestRunner.class);

上面这行代码,就可以获取一个logger的实例,然后就可以用来打印日志了。

这篇就探究这个方法都干了什么。


1

public static Logger getLogger(String name) {
ILoggerFactory iLoggerFactory = getILoggerFactory();
return iLoggerFactory.getLogger(name);
}

可以看到,只需要一个字符串name,就可以拿到logger了。这个方法位于LoggerFactory。

这里第一步是,获取ILoggerFactory。

2 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");
}

getILoggerFactory 也是LoggerFactory的一个静态方法


在LoggerFactory中,有一个并发安全的 类变量,记录的是初始化的状态。


static volatile int INITIALIZATION_STATE = UNINITIALIZED;

程序刚启动时是0,表示未初始化,还有几个状态,进行中,失败,成功等。

static final int UNINITIALIZED = 0;
static final int ONGOING_INITIALIZATION = 1;
static final int FAILED_INITIALIZATION = 2;
static final int SUCCESSFUL_INITIALIZATION = 3;
static final int NOP_FALLBACK_INITIALIZATION = 4;

这个信号作用就是控制并发,让程序中,只能有一个在做初始化的操作。其他等着就行了,因为logger系统,只用绑定一次就好了。


这里还能学习一个防止并发问题的写法。

public static ILoggerFactory getILoggerFactory() {
if (INITIALIZATION_STATE == UNINITIALIZED) {
synchronized (LoggerFactory.class) {
if (INITIALIZATION_STATE == UNINITIALIZED) {
INITIALIZATION_STATE = ONGOING_INITIALIZATION;
performInitialization();
}
}
}

....
}


下面执行初始化的方法,如下

private final static void performInitialization() {
bind();
if (INITIALIZATION_STATE == SUCCESSFUL_INITIALIZATION) {
versionSanityCheck();
}
}


这里关键的一步是bind(),绑定的主要代码

if (!isAndroid()) {
staticLoggerBinderPathSet = findPossibleStaticLoggerBinderPathSet();
reportMultipleBindingAmbiguity(staticLoggerBinderPathSet);
}
// the next line does the binding
StaticLoggerBinder.getSingleton();
INITIALIZATION_STATE = SUCCESSFUL_INITIALIZATION;
reportActualBinding(staticLoggerBinderPathSet);
fixSubstituteLoggers();
replayEvents();
// release all resources in SUBST_FACTORY
SUBST_FACTORY.clear();

先判断是不是android,不是进入括号。


findPossibleStaticLoggerBinderPathSet 找可能的StaticLoggerBinder

寻找

org/slf4j/impl/StaticLoggerBinder.class

这个类。

这个类由具体的日志框架来实现。如logback中,就会有这个类,下图

LoggerFactory.getLogger 的过程(一)_android


在找到StaticLoggerBinder这个类之后,要做一个重复检查,因为slf4j只能绑定一个底层的日志系统,如果发现多余一个,就会报告错误。

但不会中断程序启动,会在最后,打印一下,实际的绑定的哪一个,根据文档, 实际绑定哪个是是随机的,所以,还是应该把多余的排出,只保留一个StaticLoggerBinder。

SLF4J: Class path contains multiple SLF4J bindings.
SLF4J: Found binding in [jar:file:/Users/lu/.m2/repository/ch/qos/logback/logback-classic/1.2.3/logback-classic-1.2.3.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: Found binding in [jar:file:/Users/lu/.m2/repository/org/slf4j/slf4j-log4j12/1.7.26/slf4j-log4j12-1.7.26.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: See http://www.slf4j.org/codes.html#multiple_bindings for an explanation.
SLF4J: Actual binding is of type [ch.qos.logback.classic.util.ContextSelectorStaticBinder]


spring boot 默认使用的是logback。




标签:StaticLoggerBinder,INITIALIZATION,slf4j,getLogger,STATE,static,LoggerFactory,过程
From: https://blog.51cto.com/u_15815563/5848519

相关文章