前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >slf4j、log4j、log4j2、logback到底用哪些jar

slf4j、log4j、log4j2、logback到底用哪些jar

作者头像
叫我阿柒啊
发布2022-05-09 20:16:57
2750
发布2022-05-09 20:16:57
举报
前言

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来看看程序输出的结果是否符合自己的预期。后来发现这种方式真的有点low,从JDK1.4开始提供java.until.logging,后来大佬发现JUL太难用了,就自己手撸了个log4j,后来log4j发现安全漏洞,加上代码结构问题难以维护,于是从1.2就停止更新log4j,并又重新手撸了个log4j2,后来这个大佬手撸了一个性能更高、功能更全的logback,从此,这个大佬构建了log的世界,也创造了最常见的日志框架:log4j、log4j2、logback。

SLF4J( Simple Logging Facade for Java )

目前已经提及的四个日志框架,如果我们想用来记录日志的话,需要完成它们必要的配置,并且在代码中获取Logger,打印日志。引入代码如下:

代码语言:javascript
复制
// 使用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,还得需要修改代码。如果100个class中使用了jul,就得修改100个地方,这是多么一个繁琐的工作。于是Apache Commons Logging出现了。Common-logging提供了一个日志入口,称作"门面日志",即它不负责写日志,而是提供用一个统一的接口,通过jar来决定使用的日志框架,这样就不要再更换框架的时候再修改代码了。后来开发了log4j的大佬在嫌弃Common-logging难用之后又开发了同样功能的slf4j,今天就拿slf4j讲述门面日志。门面日志和设计模式中的外观模式如出一辙,就是为子系统提供统一的入口,封装子系统的复杂性,便于客户端调用。slf4j就像是菜鸟驿站,本身没有快递服务,但是提供顺丰、中通等快递服务,至于你想用顺丰还是用中通,完全取决于你的想法。

使用slf4j的代码如下:

代码语言:javascript
复制
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如何决定使用哪个框架日志呢?如slf4j官方图所示:

这就是slf4j和其他框架的组合,使用slf4j需要首先导入slf4j-api.jar,和log4j配合,你就要导入log4j.jar,以及他们之间的桥接包slf4j-log412.jar。这个官方图美中不足的地方是,没有log4j2的配合方式,和log4j2配合需要导入桥接包log4j-slf4j-impl.jar和log4j2的log4j-api.jarlog4j-core.jar。logback只需要导入logback-classiclogback-core.jar即可,不需要桥接包。

什么是桥接包,为什么logback没有

先让来让我们看看slf4j从LoggerFactory.getLogger()开始,到底干了什么。流程图如下:

原理就是就是让ClassLoader从classpath(依赖的jar)中找到StaticLoggerBinder这个类,然后利用他来返回log4j、logback等Logger,然后实现打印日志。所谓的桥接包,就是实现了StaticLoggerBinder类来连接slf4j和日志框架。因为log4j和log4j2刚开始没有StaticLoggerBinder这个类,为了不改变程序结构,于是写了一个新的包来实现StaticLoggerBinder。而logback出现slf4j之后,所以就在logback中实现了StaticLoggerBinder,所以就不需要桥接包。StaticLoggerBinder大致实现了本文第一段代码里面的功能,各自的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及其应用有帮助。

如果您有想了解的知识可以私信,如果我对您想了解的知识点略懂,我会抽空整理一份文章。

slf4j官网:http://www.slf4j.org/manual.html

log4j官网:https://logging.apache.org/log4j/2.x/

logback官网:http://logback.qos.ch/

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2020-07-31,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 入门到放弃之路 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
  • log发展历史
  • SLF4J( Simple Logging Facade for Java )
  • 什么是桥接包,为什么logback没有
  • 使用总结
  • 结语
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档