简单总结日志管理
系统梳理一下 Spring Boot 中的日志体系,包括涉及到的组件、它们之间的区别、优势、以及使用上的一些关键知识点。
一、Spring Boot 默认用到的日志组件
Commons Logging (Jakarta Commons Logging, JCL)
- Spring 框架本身最早使用的日志门面(facade)。
- Spring Boot 会把它桥接到 SLF4J。
SLF4J (Simple Logging Facade for Java)
- 日志门面:只定义接口,不负责日志的具体实现。
- 常用的接口方法:
logger.info(),logger.debug(),logger.error()等。 - 优点:屏蔽底层实现差异,支持灵活替换。
Logback
- Spring Boot 默认的日志实现(在
spring-boot-starter-logging里)。 - 高性能,支持异步日志,支持灵活的配置(
logback-spring.xml)。 - 提供分级别日志、滚动日志、异步输出等。
- Spring Boot 默认的日志实现(在
Log4j2
- 新一代的 Log4j,性能比 Logback 更强,支持异步日志(基于 LMAX Disruptor)。
- 配置文件灵活(XML、JSON、YAML)。
- 需要替换默认依赖:排除
spring-boot-starter-logging,引入spring-boot-starter-log4j2。
Java Util Logging (JUL)
- JDK 自带的日志框架,功能较弱,扩展性差。
- 一般只作为兼容层使用。
二、它们之间的区别和优势
| 组件 | 类型 | 优势 | 劣势 |
|---|---|---|---|
| Commons Logging | 门面 | 早期 Spring 框架支持 | 已被 SLF4J 替代 |
| SLF4J | 门面 | 统一日志 API,桥接能力强 | 需要绑定实现 |
| Logback | 实现 | 默认,性能好,配置强大 | 启动速度比 Log4j2 慢一点 |
| Log4j2 | 实现 | 性能极佳,异步日志领先 | 需要手动替换 |
| JUL | 实现 | 自带,零依赖 | 功能弱,扩展性差 |
三、日志等级与生效配置
日志级别从高到低(优先级):
ERROR > WARN > INFO > DEBUG > TRACE
- 如果配置了
INFO,则 INFO、WARN、ERROR 会输出,DEBUG、TRACE 不会。 - Spring Boot 默认等级是
INFO。
配置方式:
1 | logging: |
也可以在 application.properties 中:
1 | logging.level.root=INFO |
例子:如果只想在控制台打印执行的sql,但是不打印结果,可以设置相关包路径DEBUG,
四、日志分层管理的原理
日志框架是怎么做到“分层管理”,以及日志等级是怎么注册、生效的。我分几个步骤来讲清楚整个原理(以 SLF4J + Logback 为例,Log4j2 原理类似)。
1. 日志体系的分层模型
日志的“分层管理”来自 Logger 的层级树结构,对应 包名/类名的层次:
每一个类通常会定义自己的
Logger,如:1
private static final Logger logger = LoggerFactory.getLogger(MyService.class);
Logger的名字一般是 类的全限定名(com.example.service.MyService)。Logger 是树状结构:
1
2
3
4
5
6root
└── com
└── example
├── service
│ └── MyService
└── repository
👉 父子关系规则:
com.example是com.example.service.MyService的父 logger。- 如果子 logger 没有单独配置等级,就会继承父 logger 的等级。
2. Logger 注册过程
- 获取 Logger
- 调用
LoggerFactory.getLogger(clazz)。 - SLF4J 只是 facade,最终会调用底层实现(比如 Logback 的
LoggerContext)。
- 调用
- LoggerContext 管理所有 Logger
LoggerContext维护一张 logger name → Logger 对象 的 Map。- 如果请求的 logger 不存在,就新建一个,并挂在对应父 logger 下。
- 默认情况下,所有 Logger 最终都继承自 root logger。
- root logger 特殊性
- 必须存在,默认等级是
DEBUG(Logback)或INFO(Spring Boot 默认配置覆盖)。 - 所有没有明确配置的 logger 最终都会走 root 的等级。
- 必须存在,默认等级是
3. 日志等级的生效机制
日志有 5 个常用等级(Logback/Log4j2 都一样):
TRACE < DEBUG < INFO < WARN < ERROR
生效过程:
设置等级
可以针对
root或某个具体包/类配置等级:1
2logging.level.root=INFO
logging.level.com.example.service=DEBUG
日志调用时判断
- 调用
logger.debug("...")→ Logger 会先检查自己的 有效等级(effective level)。 - 有效等级的计算方式:
- 当前 logger 有配置 → 使用当前等级
- 没有配置 → 继承父 logger 的等级(逐层向上找,直到 root)
- 调用
等级比较
- 如果
调用等级 >= 有效等级→ 允许打印 - 否则丢弃,不进入 appender。
- 如果
例如:
1 | logging.level.root=INFO |
logger.debug()在com.example.MyClass→ 会输出(因为生效等级 DEBUG ≤ 调用等级 DEBUG)。logger.debug()在org.springframework.web→ 不输出(继承 root,生效等级 INFO,DEBUG < INFO)。
4. Appender 与 Filter 生效
- 日志被判断“允许输出”后,会传给 Appender(输出器,比如 console/file)。
- Appender 可以再挂 Filter(比如只允许 WARN+)。
- 最终决定是否写入日志目标。
5. 小结(原理串起来)
- 注册:
LoggerFactory.getLogger()→ LoggerContext 查找/创建 Logger → 挂到层级树上。 - 生效等级:
每个 Logger 都有一个“有效等级”,优先取自己的配置,否则继承父级,一直回退到 root。 - 调用时判断:
logger.debug()→ 判断调用等级和有效等级 → 通过则进入 Appender。 - Appender 输出:
日志事件传递到 Appender → 可能经过 Filter → 最终写到控制台/文件。
📌 一句话总结:
日志分层管理的原理就是:Logger 以包/类为树状结构组织,等级自顶向下继承,调用时逐级比较有效等级,满足条件才会进入输出器。
五、SLF4J 是怎么管理多个实现的
SLF4J 本身不做日志输出,它通过 绑定(binding jar) 来决定最终使用哪个实现:
常见的绑定包:
slf4j-logback→ 绑定 Logbackslf4j-log4j2→ 绑定 Log4j2jul-to-slf4j→ 把 JUL 桥接到 SLF4J
桥接机制:
如果系统中混用多个日志框架,SLF4J 提供桥接器来把其他日志统一路由到一个实现:jcl-over-slf4j→ 把 Commons Logging 转发到 SLF4Jlog4j-over-slf4j→ 把 Log4j 转发到 SLF4Jjul-to-slf4j→ 把 JUL 转发到 SLF4J
最终,所有日志都会统一到 SLF4J,再交给某个具体实现(比如 Logback)来打印。
六、Spring Boot 使用日志的常见知识点
默认配置文件
logback-spring.xml→ 推荐 Spring Boot 扩展标签(如 profile 分组)。logback.xml→ 标准 logback 配置文件。
日志输出位置
默认输出到 控制台。
配置输出到文件:
1
2
3
4
5
6
7
8logging:
file:
name: app.log
logback:
rollingpolicy:
file-name-pattern: logs/app-%d{yyyy-MM-dd}.%i.log
max-file-size: 10MB
max-history: 30
异步日志
- Logback 支持
AsyncAppender。 - Log4j2 支持原生异步日志,性能更强。
- Logback 支持
占位符写法(避免字符串拼接浪费性能)
1
logger.debug("User id: {}, name: {}", userId, userName);
🔑 总结一句话:
Spring Boot 默认使用 SLF4J + Logback。SLF4J 负责统一 API,桥接不同实现;Logback 则负责具体日志输出。如果要追求极致性能,可以切换到 Log4j2。日志等级、输出位置和异步化是使用时的核心关注点。