日志门面slf4j和各日志框架

简介

简单日志门面(Simple Logging Facade For Java)

SLF4J主要是为了给Java日志访问提供一套标准、规范的API框架,

其主要意义在于提供接口,具体的实现可以交由其他日志框架,如log4j、logback、log4j2。

对于一般的Java项目而言,日志框架会选择slf4j-api作为门面,配上具体的实现框架,中间使用桥接器完成桥接。

所以我们可以得出SLF4J最重要的两个功能就是对于日志框架的绑定以及日志框架的桥接。

slf4j+log4j

依赖

XML 复制代码
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>1.7.21</version>
        </dependency>

        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-log4j12</artifactId>
            <version>1.7.21</version>
        </dependency>

使用入口

java 复制代码
 Logger logger = LoggerFactory.getLogger(Slf4jAndLog4j.class);
 logger.info("this is slf4j&log4j test:{}",123);

log4j的配置文件参见:log4j日志框架的使用-CSDN博客

slf4j+logback

依赖

XML 复制代码
<dependency>
    <groupId>ch.qos.logback</groupId>
    <artifactId>logback-classic</artifactId>
    <version>1.1.7</version>
</dependency>

使用入口

java 复制代码
Logger logger = LoggerFactory.getLogger(Slf4jAndLogback.class);
logger.info("this is slf4j&logback test:{}",123);

logback配置参见:logback日志框架使用-CSDN博客

slf4j+log4j2

依赖

XML 复制代码
        <!--sl4j日志门面-->
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>1.7.25</version>
        </dependency>

        <!--log4j适配器-->
        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-slf4j-impl</artifactId>
            <version>2.12.1</version>
        </dependency>

        <!--log4j2实现-->
        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-core</artifactId>
            <version>2.12.1</version>
        </dependency>

使用入口

java 复制代码
Logger logger = LoggerFactory.getLogger(Slf4jAndLog4j2.class);
logger.info("this is slf4j&log4j2 test:{}",123);

log4j2的配置参见:log4j2日志框架使用-CSDN博客

实现原理

代码解析入口:

java 复制代码
LoggerFactory.getLogger(Slf4jAndLog4j2.class);

该段代码会寻找依赖中的日志实现

如何寻找日志依赖?

org.slf4j.LoggerFactory#findPossibleStaticLoggerBinderPathSet方法会读取依赖中所有的org.slf4j.impl.StaticLoggerBinder类所在的文件路径

在工作路径下,依赖下寻找文件名为:org/slf4j/impl/StaticLoggerBinder.class 的文件。其实说白一点,就只寻找各个日志框架的桥接引导类org.slf4j.impl.StaticLoggerBinder,如下是各个日志框架实现的桥接截图:

寻找到对应的日志框架桥接的引导类之后,调用初始化操作完成日志的加载和初始化动作。这就是slf4j门面模式和各日志框架实现的原理

log4j的引导操作截图如下:

在前面的关于log4j的源码浅析(log4j日志框架的使用-CSDN博客)中,log4j的初始化LogManager类中完成的。slf4j的桥接器(StaticLoggerBinder)引导完成初始化加载

log4j2的引导操作截图如下:

在前面的关于log4j2的源码浅析(log4j2日志框架使用-CSDN博客)中,log4j2的入口是LogManager的静态代码块加载。slf4j的桥接器(StaticLoggerBinder)引导完成初始化加载

logback的引导操作可以翻看前面的文章:logback日志框架使用-CSDN博客

各日志框架性能对比

引用一张log4j2的官方性能压测数据图:

log4j2的异步日志性能明显高于log4j和logback(由于日志框架出现的时间有先后,后面的日志肯定会规避前面日志框架的缺点而继承其优点)

log4j2全异步日志开启

1 引入依赖

XML 复制代码
<dependency>
  <groupId>com.lmax</groupId>
  <artifactId>disruptor</artifactId>
  <version>3.4.2</version>
</dependency>

2 增加启动参数

java 复制代码
-Dlog4j2.contextSelector=org.apache.logging.log4j.core.async.AsyncLoggerContextSelector

或者

java 复制代码
System.setProperty("Log4jContextSelector", "org.apache.logging.log4j.core.async.AsyncLoggerContextSelector")

@slf4j注解实现原理

平时在使用slf4j门面日志配合其他日志框架时,很少会在类中通过编码定义Logger对象,而习惯性的使用@slf4j注解完成Logger定义。不知道大家想过没有,这个注解是如何实现的?

@slf4j注解是由lombok

依赖引入的,该依赖会将标注了@slf4j的类编程成形如:

复制代码
private static final Logger log = LoggerFactory.getLogger(Demo2.class);

的一个log对象

源代码如下:

编译之后的类:

相关推荐
小陈工几秒前
Python Web开发入门(一):虚拟环境与依赖管理,从零搭建纯净开发环境
开发语言·前端·数据库·git·python·docker·开源
SimonKing1 分钟前
紧急自查!Apifox被投毒,使用者速看:你的Git、SSH、云密钥可能已泄露
java·后端·程序员
Yupureki1 分钟前
《Linux系统编程》18.线程概念与控制
java·linux·服务器·c语言·jvm·c++
运维行者_3 分钟前
金融和电商行业如何使用网络监控保障业务稳定?
开发语言·网络·人工智能·安全·web安全·机器学习·运维开发
帅得不敢出门3 分钟前
Android Framework中调用由java编译成的jar接口
android·java·framework·jar
csbysj20206 分钟前
Eclipse 视图(View)详解
开发语言
zhangzeyuaaa15 分钟前
# Python 抽象类(Abstract Class)
开发语言·python
墨^O^16 分钟前
并发控制策略与分布式数据重排:锁机制、Redis 分片与 Spark Shuffle 简析
java·开发语言·c++·学习·spark
丶小鱼丶16 分钟前
数据结构和算法之【阻塞队列】上篇
java·数据结构