slf4j中jcl-over-slf4j、jul-to-slf4j、log4j-over-slf4j、slf4j-api的区别是什么

slf4j-api ------ 日志门面(核心)

是什么

  • slf4j-api是 SLF4J 的核心接口包

  • 只定义接口,不包含任何具体日志实现

    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;

作用

  • 提供统一的日志 API

  • 让业务代码不依赖具体日志实现(Logback / Log4j2 / JUL 等)

  • 实现 面向接口编程

特点

特性 说明
是否包含实现 ❌ 否
是否可单独使用 ❌ 否
是否必须引入 ✅ 是

所有 SLF4J 项目都必须引入

*-over-slf4j ------ "日志桥接器"(偷天换日)

这类 jar 的共同点是:

把别的日志框架的调用,偷偷转发给 SLF4J

它们通常用于 遗留系统 / 第三方依赖。

jul-to-slf4j(Java Util Logging → SLF4J)

解决什么问题

  • JDK 自带的日志:java.util.logging(JUL)

  • 很多 JDK 内部或老代码在用

作用

  • 将 java.util.logging.Logger的输出桥接到 SLF4J

使用方式

需要显式安装桥接 handler

复制代码
SLF4JBridgeHandler.removeHandlersForRootLogger();
SLF4JBridgeHandler.install();

特点

项目 说明
自动生效 ❌ 否
性能损耗 ✅ 有一定
是否常用 ✅ 中等

常见于 JDK 原生日志较多的系统

一句话总结

组件 一句话解释
slf4j-api 日志门面接口
jcl-over-slf4j JCL → SLF4J
jul-to-slf4j JUL → SLF4J
log4j-over-slf4j Log4j1 → SLF4J

除了slf4j-api,都是转发的作用,为什么有的用to,有的用over呢?

命名 本质区别
xxx-to-slf4j "转接":从 A 转到 SLF4J(通常较轻量)
xxx-over-slf4j "覆盖":用同名类直接盖掉原来的实现

为什么 JUL 用 to,而 JCL / Log4j 用 over?

jul-to-slf4j------ 为什么是 to?

原因 1:JUL 无法被"覆盖"
  • java.util.logging是 JDK 内置包

  • 你不能在 classpath 里放一个:

    复制代码
    java.util.logging.Logger

    会被 JVM 拒绝(安全管理 + 类加载机制)

原因 2:只能通过 Handler 转接
  • SLF4J 的做法是:

    • 给 JUL 注册一个 Handler

    • 在 Handler 里把日志事件转发给 SLF4J

      SLF4JBridgeHandler.install();

本质是:

JUL → Handler → SLF4J

所以是 to(转过去)


jcl-over-slf4j/ log4j-over-slf4j------ 为什么是 over?

原因 1:这些日志框架是"外部 jar"

  • Apache Commons Logging

  • Log4j 1.x

它们都在 应用 classpath 中,可以被覆盖。

原因 2:SLF4J 使用了"类级覆盖"

以 jcl-over-slf4j为例:

复制代码
org.apache.commons.logging.Log
org.apache.commons.logging.LogFactory

SLF4J 提供了一个 一模一样的包名 + 类名

JVM 类加载时:

  • 先加载到的是 SLF4J 的版本

  • 原有实现直接"被架空"

本质是:

旧日志 API → 同名类 → SLF4J

所以是 over(盖在上面)

从"侵入性"理解 to vs over

维度 to over
是否替换原有类 ❌ 否 ✅ 是
是否修改原框架行为 ❌ 很少 ✅ 完全接管
是否依赖类加载顺序 ❌ 否 ✅ 是
风险 低 中
典型代表 jul-to-slf4j jcl-over-slf4j log4j-over-slf4j

判断该用哪个

问自己一个问题:

这个日志框架的类,我能自己在 classpath 里"重写"吗?

  • 能 → xxx-over-slf4j

  • 不能 → xxx-to-slf4j

相关推荐
星夜离尘566 小时前
MATLAB 工程实验:不等间隔流量积分,先把缺口与覆盖率说清楚
开发语言·matlab·时间戳·数据质量·数值积分
_Evan_Yao6 小时前
Redis 缓存穿透、击穿、雪崩,一次讲清!
java·spring·mybatis
Ai-_Man6 小时前
Meta Muse还是不可以导出左侧所有对话,只能点进去单条内容导出,方法不对吗?
开发语言·人工智能·ai·小程序·c#·1024程序员节
梓豪csd6 小时前
消息订阅中心:谁该收到哪条通知
java·开发语言·人工智能·低代码·自动化·1024程序员节
秋饼6 小时前
Spring AI 2.1 Message Parts 深度实战:推理签名回放与跨轮记忆持久化的源码级落地
java·ai·技术分享·后端开发
学逆向的7 小时前
C 枚举变量
c语言·开发语言·网络安全
Sakura_j_h_7 小时前
Python 在定时任务里输出 emoji,UnicodeEncodeError 从哪来
开发语言·字符编码·windows·python·定时任务
thefool1122667 小时前
TCP 1
java·1024程序员节
金銀銅鐵9 小时前
[Java] 用 GUI 展示 EnumSet 增减元素时的内部变化(下)
java·后端·ai编程
AI人工智能+电脑小能手10 小时前
一次请求打几个下游,这个Java并行任务工具类6个方法按序聚合
java·线程池·并发编程·1024程序员节·批量处理·并行任务