认识Spring 中的日志

这篇文章你将了解到Spring生态中日志框架是如何演化集成的

Spring Boot 日志

众说周知,Spring Boot 统一了日志框架,统一使用Logback进行日志输出,不管内部依赖框架使用的何种日志,最终都以Logback输出,他为什么需要统一呢。

我们通过引入spring-boot-starter 依赖先来看看:

可见,通过spring-boot-starter引入了spring-boot、spring-boot-autoconfigure、spring-boot-starter-logging、jakarta.annotation-api、spring-core等;其中spring-boot-starter-logging主要引入日志相关的依赖,有logback-classic、log4j-to-slf4j、jul-to-slf4j,正因为有这些依赖spring boot 才能够统一日志框架,我们先看看这几个依赖的作用。

text 复制代码
logback-classic: logback的主要日志依赖  
log4j-to-slf4j:将lo4j日志桥接到了slf4j日志框架,spring 框架默认使用的,所以需要该依赖  
jul-to-slf4j:将jul日志桥接到了slf4j日志框架,tomcat框架默认使用的,jul 即Java Util Logging

正因为Spring Boot 使用到了Spring、Tomcat,但两者都各自使用了不同的日志框架,后面可能还有其他依赖框架,混乱的日志框架势必会对开发人员造成困扰。

这里我们看到两个依赖都桥接到了slf4j,那什么是slf4j?大部分人应该都知道slf4j是一种抽象日志框架,要能够输出日志,slf4j还需要绑定到具体的日志框架,比如logback-classic。那为什么会出来slf4j呢。

到目前为止Java生态有很多的日志框架:logback、log4j、log4j2、simpleLog、JUL等。这么多的日志框架,你想象一下,如果开始的时候你使用的JUL打印日志,随着新技术的发展又出来了log4j,另一波开发人员又引入了log4j,后面又出现了log4j2,多种日志框架充斥着系统,改配置就得改不同的文件,给维护带来很多麻烦。

Spring 日志

后来出现了Commons Logging(JCL),其通过统一的写法统一了框架日志,不需要根据不同的日志框架,不同的日志编码。

java 复制代码
 private Log log = LogFactory.getLog(CLASS.class);

通过如上编码,JCL会去寻找合适的日志框架,通过找到的日志框架打印日志。

但是随着时间的推移,JCL 在2014年后就没更新(2023年JCL又开始更新了一版1.3.0),后面被越来越多的人弃用,但是就如上面说的Spring 还是一直使用的JCL作为默认日志框架。

在Spring框架中有一个spring-jcl依赖,其中LogAdapter有一个静态方法块,用来选择要加载的Log API

java 复制代码
	private static final String LOG4J_SPI = "org.apache.logging.log4j.spi.ExtendedLogger";

	private static final String LOG4J_SLF4J_PROVIDER = "org.apache.logging.slf4j.SLF4JProvider";

	private static final String SLF4J_SPI = "org.slf4j.spi.LocationAwareLogger";

	private static final String SLF4J_API = "org.slf4j.Logger";


	private static final LogApi logApi;

static {
		if (isPresent(LOG4J_SPI)) {
			if (isPresent(LOG4J_SLF4J_PROVIDER) && isPresent(SLF4J_SPI)) {
				// log4j-to-slf4j bridge -> we'll rather go with the SLF4J SPI;
				// however, we still prefer Log4j over the plain SLF4J API since
				// the latter does not have location awareness support.
				logApi = LogApi.SLF4J_LAL;
			}
			else {
				// Use Log4j 2.x directly, including location awareness support
				logApi = LogApi.LOG4J;
			}
		}
		else if (isPresent(SLF4J_SPI)) {
			// Full SLF4J SPI including location awareness support
			logApi = LogApi.SLF4J_LAL;
		}
		else if (isPresent(SLF4J_API)) {
			// Minimal SLF4J API without location awareness support
			logApi = LogApi.SLF4J;
		}
		else {
			// java.util.logging as default
			logApi = LogApi.JUL;
		}
	}

如上,有一句话很有意思,
log4j-to-slf4j bridge -> we'll rather go with the SLF4J SPI; however, we still prefer Log4j over the plain SLF4J API since the latter does not have location awareness support.

如果存在log4j-to-slf4j 桥接器,那么就选择SLF4J ,但是我们还是更喜欢使用Log4j而不是SLF4J API,因为它没有位置感知支持。

LOG4J_SPI 存在于 log4j包中
LOG4J_SLF4J_PROVIDER 存在于log4j-to-slf4j中
SLF4J_SPI 存在于slf4j中
SLF4J_API存在于slf4j中

什么是位置感知?网上没有什么资料说这个问题?但我们可以问下大模型,看看怎么回答的。

好像也没错,SLF4J只是一个日志的抽象,没有具体实现,确实不能记录日志的发生位置~。

SLF4J

说回SLF4J,使用方式也跟JCL一样,只需要同样的代码,就能使用不同的日志框架。
Logger logger = LoggerFactory.getLogger(Wombat.class);

但是它比JCL更先进,只需要更换不同的绑定器,而不是将日志实现硬编码在代码中

SLF4J里面有还有两个概念,绑定器和桥接器。

绑定器:SLF4J绑定具体的日志实现框架,比如logback-classic是logback的绑定器https://slf4j.org/manual.html

桥接器:将以前的日志框架桥接到SLF4J中,使用SLF4J来确定具体的日志框架,更多的桥接器可以到官网中查看。https://slf4j.org/legacy.html

SLF4J起到了一个桥梁的工作,如同一个交通指挥员,指挥不同的日志框架如何进行转换,比JCL更灵活。


作者其他文章推荐:

基于Spring Boot 3.1.0 系列文章

  1. Spring Boot 源码阅读初始化环境搭建
  2. Spring Boot 框架整体启动流程详解
  3. Spring Boot 系统初始化器详解
  4. Spring Boot 监听器详解
  5. Spring Boot banner详解
  6. Spring Boot 属性配置解析
  7. Spring Boot 属性加载原理解析
  8. Spring Boot 异常报告器解析
  9. Spring Boot 3.x 自动配置详解
相关推荐
收破烂的小熊猫~6 分钟前
《Java修仙传:从凡胎到码帝》第四章:设计模式破万法
java·开发语言·设计模式
小七mod12 分钟前
【MyBatis】MyBatis与Spring和Spring Boot整合原理
spring boot·spring·mybatis
猴哥源码14 分钟前
基于Java+SpringBoot的动物领养平台
java·spring boot
老任与码18 分钟前
Spring AI Alibaba(1)——基本使用
java·人工智能·后端·springaialibaba
小兵张健19 分钟前
武汉拿下 23k offer 经历
java·面试·ai编程
FreeBuf_29 分钟前
Apache组件遭大规模攻击:Tomcat与Camel高危RCE漏洞引发数千次利用尝试
java·tomcat·apache
无妄-202440 分钟前
软件架构升级中的“隐形地雷”:版本选型与依赖链风险
java·服务器·网络·经验分享
qqxhb44 分钟前
零基础数据结构与算法——第四章:基础算法-排序(上)
java·数据结构·算法·冒泡·插入·选择
华子w9089258591 小时前
基于 SpringBoot+VueJS 的农产品研究报告管理系统设计与实现
vue.js·spring boot·后端
猴哥源码1 小时前
基于Java+SpringBoot的在线小说阅读平台
java·spring boot