实习生问我:为什么用Logback不用Log4j?我讲了一个小时的江湖恩怨
前言
公司新来的实习生最近问我几个问题,说我们为什么要用logback?为什么不用log4j?它们的区别是什么?
这么多日志框架,到底该用哪个?
我不禁想起了自己刚接触 Java 时面对日志选择的困惑。
Java各种日志框架的“江湖恩怨”确实让不少开发者,无论是新手还是老鸟,都感到有些头疼。
各种框架层出不穷,依赖关系错综复杂,稍不注意就可能掉进“坑”里。
为了让更多对 Java 日志体系还不太清晰的朋友们能够拨云见日,我决定花点时间,系统地梳理一下这些常见的日志框架,聊聊它们的前世今生。
希望能帮助各位在实际项目中做出明智的选择。
耐心看完,你一定有所收获。
正文
很久以前:System.out.println 🤦
最早的时候,我们并没有什么正经的日志框架。想看程序运行到哪了,变量是什么值,怎么办?
简单粗暴——System.out.println() 和 System.err.println()。
这种方式在临时调试时还凑合,但一旦项目复杂起来,缺点就出来了:
- 日志满天飞,重要信息找不到。
- 不能分级(DEBUG, INFO, ERROR等)输出。
- 大量的控制台IO反而会拖慢系统。
- 日志信息在程序结束后就没了,不能输出到文件。
- 每个人打印的格式可能都不一样,难以解析。
显然,这不够用。
于是,英雄登场。
Log4j 1.x:曾经的王者 👑
大约在2001年,Ceki Gülcü 大神开源了 Log4j(通常指1.x版本)。
这是个革命性的工具。
它引入了几个核心概念,至今仍在被各大日志框架沿用:
- Logger (日志记录器) :负责发起日志记录请求。Logger之间有层级关系,类似Java包名。
- Appender (输出目的地) :负责将日志输出到不同地方,比如控制台(
ConsoleAppender)、文件(FileAppender、RollingFileAppender)、数据库(JDBCAppender)等。 - Layout (日志格式化器) :负责格式化日志信息,可以定义输出的时间、级别、线程名、类名、方法名、日志内容等。
- Level (日志级别) :常见的有
TRACE,DEBUG,INFO,WARN,ERROR,FATAL。可以设置Logger的级别,只输出大于等于该级别的日志。
Log4j 凭借其强大的功能和灵活性,迅速风靡一时。很多开源框架,如早期的Spring、Hibernate等都依赖它。
但注意:Log4j 1.x 在 2015 年就停止维护了 (EOL),而且有已知的安全漏洞!
所以,💀 请勿使用!
大厂机会
想选一个大厂作为跳板,作为自己镀金机会的,尤其是看【上海】【深圳】等→机会的朋友,前端-测试-后端!待遇薪酬还不错,尽管来!
混乱的过渡期:JCL 与 JUL
JCL (Jakarta Commons Logging)
正当 Log4j 风头正劲时,Apache 觉得,如果每个组件都依赖特定的日志实现(比如都依赖Log4j),那万一我想换个日志实现怎么办?岂不是要改断腿?
于是,JCL (Jakarta Commons Logging,后来也叫 Apache Commons Logging) 诞生了。
它的初衷是好的:提供一个日志门面 (Facade) 。你的应用程序代码只需要依赖 JCL 的API,JCL 会在运行时动态查找并绑定到一个实际的日志实现(比如 Log4j 或 JDK自带的日志)。
理想很丰满,现实很骨感。
JCL 的动态查找机制在复杂的类加载器环境下(比如各种应用服务器)经常出问题,导致著名的 “commons-logging hell” ,开发者总是为了解决依赖冲突而头疼。
JUL (Java Util Logging)
Sun公司一看,日志这么重要的东西,怎么能没有官方的呢?
于是在 Java 1.4 中引入了 java.util.logging (JUL)。
JUL 的好处是它是 JDK 自带的,不需要引入额外依赖。但它的API设计和配置相对 Log4j 来说比较拉跨,性能也一度被人诟病。
因此用的人也很少。
新一代门面:SLF4J (Simple Logging Facade for Java)
面对 JCL 的混乱和 JUL 的不温不火,Log4j 的作者 Ceki Gülcü 大神看不下去了。
他认为 JCL 的设计存在缺陷,于是另起炉灶,在2006年左右创建了 SLF4J (Simple Logging Facade for Java) 。
SLF4J 的核心思想也是门面模式,但它采用了更清晰、更稳健的绑定机制:
- 你的代码只依赖 slf4j-api.jar
- 再加入一个“绑定包” ,桥接SLF4J到具体的日志实现。例如:slf4j-log4j12.jar:将SLF4J的调用桥接到 Log4j 1.x。slf4j-jdk14.jar:桥接到 JUL。logback-classic.jar:桥接到 Logback (Logback 本身就实现了SLF4J的接口)。log4j-slf4j-impl.jar:桥接到 Log4j 2。
SLF4J 通过在编译时就确定唯一的绑定,避免了JCL在运行时动态查找带来的类加载器问题。
同时 SLF4J 还提供了一些更方便的API,比如占位符语法:
// 传统 Log4j/JUL 写法,有字符串拼接开销
logger.debug("User " + user.getName() + " logged in from " + ipAddress);
// SLF4J 写法,只有当debug级别启用时才会实际拼接字符串,性能更好
logger.debug("User {} logged in from {}", user.getName(), ipAddress);
由于其简洁、高效、稳定,SLF4J 迅速取代 JCL,成为业界公认的最佳日志门面。
现在,几乎所有的现代Java库和框架都推荐或默认使用 SLF4J 作为日志门面。
Logback:SLF4J 的天作之合 💖
Logback:Log4j 的精神继承者
Ceki Gülcü 在创建 SLF4J 之后,觉得 Log4j 1.x 的架构已经有些陈旧,难以适应新的需求。于是,他着手开发了一个全新的日志实现,作为 Log4j 1.x 的“精神续作”—— Logback。
Logback 被设计为 SLF4J 的原生实现(logback-classic.jar 直接实现了SLF4J的接口,所以它同时是API实现和绑定),并带来了不少亮点:
- 性能提升:比 Log4j 1.x 快很多,内存占用也更少。
- 原生SLF4J支持:无需额外桥接包,天生一对。
- 自动重载配置:修改日志配置文件后,无需重启应用即可生效。
- 更强大的过滤器 (Filters) :可以根据各种条件(MDC、Marker、时间、日志级别等)进行精细的日志过滤。
- TurboFilter:非常高效的过滤器,可以在日志事件创建之前就决定是否拒绝。
- SiftingAppender:可以根据运行时属性(如用户ID、线程名)动态分离日志到不同的文件或Appender。
- 优雅地处理I/O失败:当磁盘满或网络问题时,Logback能更优雅地处理,避免拖垮应用。
- Spring Boot 默认:开箱即用,省心。
由于这些显著的优势,Logback 迅速流行起来,成为很多项目(包括 Spring Boot 默认)的首选日志实现。
这就是为什么很多公司选择 Logback 的原因:它稳定、高效、功能强大,并且与 SLF4J 完美集成。
Log4j 2:Log4j 的进化 🚀
Log4j 1.x 社区也意识到了自身的问题和来自 Logback 的竞争压力。Apache 软件基金会组织力量,对 Log4j 进行了彻底的重新设计和重写,推出了 Log4j 2。
Log4j 2 与 Log4j 1.x 并不兼容,它是一个全新的框架,借鉴了 Logback 的一些优点:
- 异步日志:性能极高,基于LMAX Disruptor,适合高并发。
- 无垃圾/低垃圾模式:减少GC压力。
- 插件化:扩展性好。
- 支持多种配置格式:XML, JSON, YAML等。
- 也支持SLF4J:通过
log4j-slf4j2-impl.jar桥接。
Log4j 2 非常强大,尤其在追求极致性能和低延迟的场景下,它的异步日志器表现优异。
怎么选?Logback还是Log4j 2?🤔
- 门面先行:代码中永远面向SLF4J API编程!
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class MyClass {
private static final Logger logger = LoggerFactory.getLogger(MyClass.class);
// ...
}
- 实现二选一 (Logback vs Log4j 2) :
- Log4j 1.x:绝对不要用! ❌ 有安全漏洞,已停止维护。
- Logback:👍 通用首选。足够快,稳定,功能丰富。Spring Boot 默认,社区成熟,资料多。配置相对简单,上手快。
- Log4j 2:🔥 追求极致性能可选。特别是其异步日志器非常出色。需要其低GC特性或高级插件。配置稍复杂,但功能更强大。
简单来说:
- 大部分项目:SLF4J + Logback 就够了,又稳又好用。
- 性能要求苛刻或需要特定高级功能:可以考虑 SLF4J + Log4j 2。
结尾
希望那位实习生小哥听完这番“江湖恩怨录”,下次再碰到日志问题,能微微一笑,从容配置,内心OS:“就这?拿来吧你!” 😎
长江后浪推前浪,希望在座的各位也像这些日志框架一下,能把我们这些前浪狠狠地拍下~
——转载自:一只叫煤球的猫
#牛客在线求职答疑中心#