一文讲尽门面日志slf4j和log4j、log4j2、logback依赖jar引用关系
前言
之前都是使用SparkStreaming开发,最近打算学习一下Flink,就从官网下载了Flink 1.11,打算搞一个客户端,将程序提交在yarn上。因为Flink从1.7之后就不再提供Hadoop的依赖,所以很多依赖就要自己下载,于是各种ClassNotFoundException,其中以log*.class为首的格外猖狂,可能是因为flink和Hadoop的日志实现有点区别,就一直哐哐哐报错,slf4j、log4j、logback各种jar包十几个,百度好久也没搞清各个jar有什么区别,用在何处,就打算自己总结一下。
log发展历史
Long long Ago,和刚学Java的时候一样,都是用System.out.println控制台打印来检查程序输出是否符合自己的预期,这是一种比较原始的方法,无法自动区分日志的类型,几乎无法用于生产系统中。
从JDK1.4开始提供java.until.logging日志框架来打印日志,但是大佬觉得JUL太难用了,就自己手撸了个log4j,后来log4j发现安全漏洞,加上代码结构问题难以维护,于是从1.2就停止更新log4j,并又重新手撸了个log4j2,再后来,这个大佬又双手撸了一个性能更高、功能更全的logback。
从此,这个大佬构建了log的世界,也创造了最常见的日志框架:log4j、log4j2、logback。
SLF4J( Simple Logging Facade for Java )
目前已经提及了四个日志框架,如果我们想用来记录日志,除了必要的配置文件,还需要在代码中获取Logger,打印日志。
代码如下:
// 使用log4j,需要log4j.jar
import org.apache.log4j.Logger;
Logger logger_log4j = Logger.getLogger(Test.class);
logger_log4j.info("Hello World!");
// 使用log4j2,需要log4j-api.jar、log4j-core.jar
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
Logger logger_log4j2 = LogManager.getLogger(Test.class);
logger_log4j2.info("Hello World!");
// logback,需要logback-classic.jar、logback-core.jar
import ch.qos.logback.classic.Logger;
import ch.qos.logback.classic.LoggerContext;
Logger logger_logback = new LoggerContext().getLogger(Test.class);
logger_logback.info("Hello World!");
// java.until.logging,简称jul
import java.util.logging.Logger;
Logger logger_jul = Logger.getLogger("java.Test");
为什么要使用门面系统
从上面不难看出,使用不同的日志框架,就要引入不同的jar包,使用不同的代码获取Logger。
假设一个项目在漫长的升级过程中,想从jul升级到logback,那么就需要修改代码来获取新的Logger。如果100个class中使用了jul,就得修改100个地方,这是多么一个繁琐的工作!!
门面系统的作用
于是Apache Commons Logging出现了。
Common-logging提供了一个日志入口,称作"门面日志",即它不负责写日志,而是「提供用一个统一的接口,通过jar来决定使用的日志框架」,这样就不要再更换框架的时候再修改代码了。后来开发了log4j的大佬又因为嫌弃Common-logging难用,开发了门面日志框架「slf4j」,今天就拿slf4j讲述门面日志。
门面日志和设计模式中的外观模式如出一辙,本身不提供服务,为子系统提供统一的入口,封装子系统的复杂性,便于客户端调用。slf4j就像是菜鸟驿站,本身没有快递服务,但是提供顺丰、中通等快递服务,至于你想用顺丰还是用中通,完全取决于你的想法。
使用slf4j的代码如下:
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
Logger logger = LoggerFactory.getLogger(Test.class);
logger.info("Hello World!")
这行代码就像是你在菜鸟驿站里要寄东西(logger),思考到底用哪家快递?A minute later... 决定用顺丰(logback),就填了顺丰的快递单(放入logback.jar),但是你看微信余额还有10块,钱不够,只能用中通(log4j),于是你就退了顺丰的单子(移除logback.jar),填了中通的快递单(放入log4j.jar),然后发出快递(打印日志)。
那么slf4j如何决定使用哪个框架日志呢,并且引入哪些jar包呢?
如slf4j官方图所示:

如图就是slf4j和日志框架的组合依赖结构图,使用slf4j需要首先导入「slf4j-api.jar」,
和log4j配合,需要导入「log4j.jar」,以及桥接包「slf4j-log412.jar」。
官方图美中不足的是没有log4j2依赖jar的关系,和log4j2配合需要导入log4j2的「log4j-api.jar」、「log4j-core.jar」和桥接包「log4j-slf4j-impl.jar」。
logback只需要导入「logback-classic.jar」和「logback-core.jar」即可,不需要桥接包。
什么是桥接包,为什么logback没有
先让来让我们看看slf4j从LoggerFactory.getLogger()开始,到底干了什么。
流程图如下:

原理就是就是让ClassLoader从classpath(依赖的jar)中找到「StaticLoggerBinder」这个类,然后利用他来返回log4j、logback中的Logger,然后打印日志。
所谓的桥接包,就是实现StaticLoggerBinder类,用来连接slf4j和日志框架。因为log4j和log4j2刚开始没有StaticLoggerBinder这个类,为了不改变程序结构,只能重新写一个新的jar来实现StaticLoggerBinder。而logback出现slf4j之后,于是在logback本身的jar中实现了StaticLoggerBinder,所以就不需要桥接包。
StaticLoggerBinder实现了使用底层日志框架创建Logger的功能,各自的StaticLoggerBinder为slf4j提供的Logger,再提供给用户打印日志。
log4j和log4j2桥接包及logback依赖里,都有StaticLoggerBinder类。



使用总结
"Class path contains multiple SLF4J bindings."
在使用slf4j的时候会遇到以上的报告信息。我也曾遇到过web服务因为slf4j问题启动失败。究其根本是因为logback-classic、log4j-slf4j-impl、slf4j-log412、slf4j-jdk这些jar不能同时存在。他们都实现了StaticLoggerBinder类而导致冲突,slf4j无法确定到底用哪个日志框架。
结语
以上是结合官网以及自己调试代码的一些总结,希望对大家了解slf4j及其应用有帮助,其中不足的地方还望指出,共同进步,共勉!!!
写的都是日常工作中的亲身实践,处于自己的角度从0写到1,保证能够真正让大家看懂。
文章会在公众号 [「入门到放弃之路」] 首发,期待你的关注。

一文讲尽门面日志slf4j和log4j、log4j2、logback依赖jar引用关系的更多相关文章
- Java日志框架SLF4J和log4j以及logback的联系和区别
1.SLF4J(Simple logging Facade for Java) 意思为简单日志门面,它是把不同的日志系统的实现进行了具体的抽象化,只提供了统一的日志使用接口,使用时只需要按照其提供的接 ...
- slf4j、log4j、 logback关系详解和相关用法
slf4j log4j logback关系详解和相关用法 写java也有一段时间了,一直都有用slf4j log4j输出日志的习惯.但是始终都是抱着“拿来主义”的态度,复制粘贴下配置文件就开始编码了, ...
- slf4j和log4j、logback
现在主流java项目一般使用slf4j+log4j的日志方案,最近抽点时间扫了一下slf4j.log4j.logback的官方文档,做个笔记.这篇比较不打算描述具体的配置方法,因为官方文档已经讲得很清 ...
- 常见java日志系统的搭配详解:关于slf4j log4j log4j2 logback jul jcl commons-logging jdk-logging
先看一张图: 是不是有点晕, 晕就对了.这个仅仅是 slf4j 的情况,实际上, 我们不仅要接触到 slf4j ,有时候还会接触其他的日志系统.且看下文分解. 1 直接使用各个日志系统 1.1 直接使 ...
- Log4j,Log4j2,logback,slf4j日志学习
日志学习笔记 Log4j Log4j是Apache的一个开放源代码项目,通过使用Log4j,我们可以控制日志信息输送的目的地是控制台.文件.数据库等:我们也可以控制每一条日志的输出格式:通过定义每一条 ...
- Java日志之Slf4j,Log4J,logback原理总结
几乎任何应用,一定是需要日志的. 那么,面对种类繁多的日志框架和配置,我们该何去何从? 1.前奏:我是在研究mybatis源码的过程中才意识到需要搞明白日志原理这回事,因为mybatis(和一些其他开 ...
- Log4j,Log4j2,logback,slf4j日志学习(转)
日志学习笔记Log4jLog4j是Apache的一个开放源代码项目,通过使用Log4j,我们可以控制日志信息输送的目的地是控制台.文件.数据库等:我们也可以控制每一条日志的输出格式:通过定义每一条日志 ...
- SLF4J其实只是一个门面服务而已,他并不是真正的日志框架,真正的日志的输出相关的实现还是要依赖Log4j、logback等日志框架的。
小结: 1.加层: 每一种日志框架都有自己单独的API,要使用对应的框架就要使用其对应的API,这就大大的增加应用程序代码对于日志框架的耦合性. 为了解决这个问题,就是在日志框架和应用程序之间架设一个 ...
- Spring Boot 第三弹,一文带你了解日志如何配置?
前言 日志通常不会在需求阶段作为一个功能单独提出来,也不会在产品方案中看到它的细节.但是,这丝毫不影响它在任何一个系统中的重要的地位. 今天就来介绍一下Spring Boot中的日志如何配置. Spr ...
随机推荐
- PyQt(Python+Qt)学习随笔:print标准输出sys.stdout以及stderr重定向QTextBrowser等图形界面对象
专栏:Python基础教程目录 专栏:使用PyQt开发图形界面Python应用 专栏:PyQt入门学习 老猿Python博文目录 <在Python实现print标准输出sys.stdout.st ...
- PyQt(Python+Qt)学习随笔:QScrollArea的widgetResizable属性
老猿Python博文目录 专栏:使用PyQt开发图形界面Python应用 老猿Python博客地址 滚动区域的widgetResizable属性用于控制滚动区域的内容部署层是否应跟随滚动区域的大小变化 ...
- PyQt(Python+Qt)学习随笔:QListWidget获取指定位置对应项的itemAt方法
老猿Python博文目录 专栏:使用PyQt开发图形界面Python应用 老猿Python博客地址 itemAt方法根据参数给定位置返回列表部件中的项.对应语法如下: QListWidgetItem ...
- PyQt(Python+Qt)学习随笔:clicked和clicked(bool)信号连接同名函数出现的问题
在Qt中,控件中的clicked()信号和clicked(bool)信号是两个不同的信号,映射槽函数时,clicked()信号映射到的槽函数是不带参的,clicked(bool)信号映射到的槽函数是带 ...
- upload 注意php远程安全模式屏蔽函数
进来:上传一个一句话php,果然不行:改成jpg后缀,上传成功:接着写一个.htaccess文件去把.jpg解析成.php,如下: AddType application/x-httpd-php .j ...
- 小齐读者拿到快手、百度、网易等 offer 的独门秘籍!
小齐说: 这篇文章来自读者冰红茶,他刚结束了秋招,拿了很多家 offer. 和他聊完之后,我觉得他的备考思路也完全适用于美国的面试,只是分值要调整一下,但是具体每一块的内容,地球村通用.所以分享给大家 ...
- Linux安装Mycat1.6.7.4并实现Mysql数据库读写分离简单配置
1. Mycat简介 一个彻底开源的,面向企业应用开发的大数据库集群 支持事务.ACID.可以替代MySQL的加强版数据库 一个可以视为MySQL集群的企业级数据库,用来替代昂贵的Oracle集群 一 ...
- 最详细10招Spark数据倾斜调优
最详细10招Spark数据倾斜调优 数据量大并不可怕,可怕的是数据倾斜 . 数据倾斜发生的现象 绝大多数 task 执行得都非常快,但个别 task 执行极慢. 数据倾斜发生的原理 在进行 shuff ...
- 是的,你没看错!Python可以实现自动化办公
是的,你没看错!Python可以实现自动化办公 公众号[伤心的辣条],如今越来越多的人加入到学习Python的队伍当中,尤其是对于很多职场人来说,不管你是程序员还是非程序员,Python已经为很多职场 ...
- sqli-labs 18-19 --Header_injection
sqli-labs 18 知识点 头部注入 报错注入 使用的函数: updatexml (XML_document, XPath_string, new_value); 第一个参数:XML_docum ...