Java日志框架:slf4j作用及其实现原理

3,173 阅读2分钟

日志技术框架一览

  • JUL:JDK中的日志记录工具,也常称为JDKLog、jdk-logging。

  • LOG4J1:一个具体的日志实现框架。

  • LOG4J2:一个具体的日志实现框架,是LOG4J1的下一个版本。

  • LOGBACK:一个具体的日志实现框架,但其性能更好。

  • JCL:一个日志门面,提供统一的日志记录接口,也常称为commons-logging。

  • SLF4J:一个日志门面,与JCL一样提供统一的日志记录接口,可以方便地切换看具体的实现框架。

    注意:JUL、LOG4J1、LOG4J2、LOGBACK是日志实现框架,而JCL、SLF4J是日志实现门面(接口)

SLF4J结构概述

slf4j只是一个日志标准,并不是日志系统的具体实现。理解这句话非常重要,slf4j只做两件事情:

  • 提供日志接口
  • 提供获取具体日志对象的方法 image.png 如如上图所示:SLF4J作为日志打印实现的适配层,业务代码不需要关心具体使用哪一种日志系统,且如何打印日志。

SLF4J简单Demo

1.引入对应jar包

25         <dependency>
26             <groupId>org.slf4j</groupId>
27             <artifactId>slf4j-api</artifactId>
28             <version>1.7.32</version>
29         </dependency>
30         <dependency>
31             <groupId>ch.qos.logback</groupId>
32             <artifactId>logback-classic</artifactId>
33             <version>1.2.6</version>
34         </dependency>

2.增加配置文件 log4j2.xml 放在 resource 目录下:

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <!-- <include resource="org/springframework/boot/logging/logback/base.xml"/> -->

    <!-- 
      appenders    
     -->
    <appender name="DEFAULT-APPENDER" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>${LOG_PATH}/common.log</file>
        <encoder>
            <pattern>
                [%d] [%level] [%X{xRequestId}] %logger - %m%n
            </pattern>
            <charset>UTF-8</charset> <!-- 此处设置字符集 -->
        </encoder>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <!-- daily rollover -->
            <fileNamePattern>${LOG_PATH}/common.log.%d{yyyy-MM-dd}</fileNamePattern>
        </rollingPolicy>
    </appender>
    <!-- 
    loggers
 -->
    <logger name="com.zenlayer.zenconsole.ocs" level="INFO" additivity="false">
        <appender-ref ref="APP-DEFAULT-APPENDER"/>
        <appender-ref ref="ERROR-APPENDER"/>
    </logger>


    <root level="INFO">
        <appender-ref ref="DEFAULT-APPENDER"/>
        <appender-ref ref="ERROR-APPENDER"/>
    </root>
</configuration>

3.测试方法

private static final Logger logger = LoggerFactory.getLogger(SelectBillingOrderImplTest.class);

@Test
public void logTest() throws IOException {
    logger.info("");
    logger.warn("");
    logger.error("");
}

4.执行结果

image.png

SLF4J原理解析

1.创建Logger对象(Logger常定义为全局单例对象)

image.png 2.getLogger方法

image.png 3.拿到实力化工场,并根据日志类返回Logger对象

image.png 4.实力化日志工场

image.png 5.bind方法为slf4j的核心

image.png 6.slf4j回去classPatch 下面找所有org.slf4j.impl下StaticLoggerBinder这个类 注:存在引入多个Log实现的情况,所以slf4j返回的是一个Set集合 但是实际情况系统加载器只加载一个StaticLoggerBinder类。所以启动时会报错,且默认使用加载到的第一个Log实现类,然后调用改类的getSingleton方法

image.png

image.png 7.以上已经成功获取了ILoggerFactory 之后的逻辑是调用Factory的getLogger方法来获取Logger对象。回到了源码:3的位置

image.png 找到一种实现,我以LogBack为例:

image.png