SLF4J 日志框架与 SpirngBoot

发布时间 2023-07-14 14:55:48作者: XTvLi

SLF4J 是一个相对成熟的日志框架, 它基于外观模式(门面模式)实现了插拔式的日志实现替换功能, 而且还提供了其他日志框架的迁移方案。

迁移方案

目的 依赖库 备注
将 Apache Commons Logging 框架打印的日志桥接至 SLF4J 框架 jcl-over-slf4j 需要在构建工具中排除 jcl 的依赖
将 java.util.logging 框架打印的日志派发至 SLF4J 框架 jul-to-slf4j 需要调用 SLF4JBridgeHandler.removeHandlersForRootLogger(); 卸载 jul 中默认的 ConsoleHandler, 并且调用 SLF4JBridgeHandler.install(); 来注册 SLF4JBridgeHandler
将 log4j2 日志实现打印的日志桥接至 SLF4J 框架 log4j-over-slf4j 需要在构建工具中排除 log4j2 的依赖
将 Java Platform Logging 框架打印的日志派发至 SLF4J 框架 slf4j-jdk-platform-logging
基于 OSGI 的 SLF4J osgi-over-slf4j (没有遇到过 OSGI 的使用场景, 这个了解的不多)

日志实现

日志实现 依赖库 备注
logback logback-classic
log4j2 log4j-slf4j2-impl 由 apache 提供
log4j1 / 已弃用, 由于 log4j1 仍然存在一些安全漏洞, 因此推荐使用 reload4j 来代替 log4j1
reload4j slf4j-reload4j reload4j 是一个基于 log4j1 的分支实现, 它修复了 log4j1 中存在的已知安全漏洞
jul slf4j-jdk14 不要和 jul-to-slf4j 同时使用
slf4j-simple slf4j-simple 向标准输出流或文件进行输出的简单日志功能实现
slf4j-nop slf4j-nop 直接丢弃日志, 不进行任何记录操作

实现原理

slf4j-api 2.0 之前是通过反射获取固定的 Class 来实现与日志实现库绑定的,在 2.0 中 SLF4J 的这个机制替换为了 SPI,因此在 2.0 之前日志实现库被称作 binding 而在 2.0 及以后日志实现库被称作 provider。

与 Spring 的集成

SpirngFramework 中主要使用的是一个基于 jcl 简化的日志框架: spring-jcl, 它通过检查 classpath 下的相关 Class 来实现与 SLF4J、log4j2 或 JUL 的绑定,在 SpringBoot 中也提供了使用 logback(slf4j-api) 来作为日志实现的 spring-boot-starter-logging。

配置

SpringBoot 中通过 org.springframework.boot.context.logging.LoggingApplicationListener#initializeSystem 来委派给对应的日志系统来完成配置,如: org.springframework.boot.logging.logback.LogbackLoggingSystem#initialize -> org.springframework.boot.logging.AbstractLoggingSystem#initializeWithConventions 来完成日志系统的配置, 它会按照以下顺序进行配置:

  1. 加载 logback-test.xml、logback.xml 进行配置, 否则执行下一步
  2. 加载 logback-test-spring.xml、logback-spring.xml 进行配置, 否则执行下一步
  3. 进行编程式的默认配置

在 logback 的编程式默认配置是通过 org.springframework.boot.logging.logback.DefaultLogbackConfiguration#apply 来完成的, 通过代码可以看到系统中默认添加了一个向控制台输出的 consoleAppender, 并且会根据对配置文件中的 logging.file.namelogging.file.path 属性的判断添加一个使用 SizeAndTimeBasedRollingPolicy 的 fileAppender

SpringBoot 中 root logger 的默认打印级别是 info, 可以在配置文件中通过 logging.level.root 属性修改其日志级别。SpringBoot 中还提供了 logger 分组功能, 默认有 web, sql 两个分组, 因此也可以通过 logging.level.web 和 logging.level.sql 修改相关 logger 的日志级别。

SpringBoot 中默认配置的两个 appender 基本可以满足大多数的使用需求, 因此推荐通过 Spring 配置文件或者编程式微调相关配置是最便捷的使用方案。