日志框架那点破事——slf4j

2019-06-12  本文已影响0人  扎瓦叔叔

背景就不介绍了,总之是那些over,to,slf4j+log4j,slf4j+log4j2,commons-logging,一言以蔽之,何等乱七八糟!

看资料的时候觉得两张图不错,扒过来的,链接在最后参考文章中


1.png 2.png

slf4j

那先来看slf4j,slf4j就是个日志的接口,没有提供任何实现

Logger

Logger类是入口方法,是个interface,具体的日志实现框架会实现这些接口

ILoggerFactory

获取Logger的接口类,具体的日志实现框架需实现getLogger()方法

LoggerFactory

静态绑定具体日志实现框架,提过Logger对象

NOPLogger

slf4j自带的Logger的实现类

流程

流程上都是先通过LoggerFactory获取Logger,然后通过Logger记录日志

获取Logger

通过静态方法getLogger(Class clazz)获取

public static Logger getLogger(Class<?> clazz) {
    Logger logger = getLogger(clazz.getName());
    if (DETECT_LOGGER_NAME_MISMATCH) {
        Class<?> autoComputedCallingClass = Util.getCallingClass();
        if (autoComputedCallingClass != null && nonMatchingClasses(clazz, autoComputedCallingClass)) {
            Util.report(String.format("Detected logger name mismatch. Given name: \"%s\"; computed name: \"%s\".", logger.getName(),
                            autoComputedCallingClass.getName()));
            Util.report("See " + LOGGER_NAME_MISMATCH_URL + " for an explanation");
        }
    }
    return logger;
}

getLogger(Class clazz)再通过getLogger(String name)使用ILoggerFactory.getILoggerFactory()方法获取ILoggerFactory实例,就如上面说的,ILoggerFactory是用来获取Logger对象的接口类

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

这里的初始化有5个状态
UNINITIALIZED 未初始化
ONGOING_INITIALIZATION 正在被初始化
FAILED_INITIALIZATION 初始化失败
SUCCESSFUL_INITIALIZATION 初始化成功
NOP_FALLBACK_INITIALIZATION 空状态,表示无底层日志实现框架时的结果

INITIALIZATION_STATE初始化值是UNINITIALIZED,这里标记为ONGOING_INITIALIZATION后,进入bind流程。findPossibleStaticLoggerBinderPathSet()方法寻找StaticLoggerBinder.class 文件,StaticLoggerBinder类实现了LoggerFactoryBinder接口的getLoggerFactory(),pom未添加日志实现依赖包的话是找不到StaticLoggerBinder.class 文件的

当找不到StaticLoggerBinder.class 文件时,则走到NoClassDefFoundError异常,INITIALIZATION_STATE = NOP_FALLBACK_INITIALIZATION,则会用LoggerFactory下的NOPLoggerFactory对象,而NOPLoggerFactory基本是个空实现(所以最后输出也是空)

真正实现在log4j-api-2.x上,通过log4j-slf4j-impl-2.x把slf4j桥接到log4j2上(我自己的项目),第三方日志实现框架提供logger对象和log.trace()等等方法

参考文章:
1、https://www.infoq.cn/article/double-checked-locking-with-delay-initialization
2、https://www.itcodemonkey.com/article/1725.html
3、http://techblog.ppdai.com/2018/07/04/20180704/

上一篇 下一篇

猜你喜欢

热点阅读