一、简单看结构
1、结构图
1.1、对pom.xml鼠标右键
image.png
1.2、结构图
image.png
PS:看不清?没关系,自己去自己电脑上操作查看去。
二、具体分析
1、主要结构图
image.png
2、概括
我们可以从上图中看到,springboot
依赖了spring-boot-starter
,而spring-boot-starter
依赖了spring-boot-starter-logging
。
所以大概是如下这样的:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId></dependency>
SpringBoot用如下这个依赖来做日志功能:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-logging</artifactId></dependency>
3、继续分析结构图
image.png
4、总结
1、SpringBoot底层也是使用slf4j+logback的方式进行日志记录。
2、SpringBoot底层也依赖了一些桥接jar,来将其他的日志都替换成了slf4j。
5、桥接jar?
5.1、jul-to-slf4j
image.png
1)、见名知意,SLF4J桥接处理器。
2)、代码实际运用的是slf4j,如下:
/** * Return the Logger instance that will be used for logging. */protected Logger getSLF4JLogger(LogRecord record) { String name = record.getLoggerName(); if (name == null) { name = UNKNOWN_LOGGER_NAME; } return LoggerFactory.getLogger(name); }
5.2、log4j-over-slf4j
image.png
1)、太明显了,包名都没换,包名都是
org.apache.log4j
2)、实际运用的是SLF4J,如下
void differentiatedLog(Marker marker, String fqcn, int level, Object message, Throwable t) { String m = convertToString(message); if (locationAwareLogger != null) { locationAwareLogger.log(marker, fqcn, level, m, null, t); } else { switch (level) { case LocationAwareLogger.TRACE_INT: slf4jLogger.trace(marker, m); break; case LocationAwareLogger.DEBUG_INT: slf4jLogger.debug(marker, m); break; case LocationAwareLogger.INFO_INT: slf4jLogger.info(marker, m); break; case LocationAwareLogger.WARN_INT: slf4jLogger.warn(marker, m); break; case LocationAwareLogger.ERROR_INT: slf4jLogger.error(marker, m); break; } } }
PS:可以看到都是用的slf4jLogger来输出的日志。
5.3、jcl-over-slf4j
image.png
1)、太明显了,包名都没换,包名都是
org.apache.log4j
2)、实际运用的是SLF4J,如下
public abstract class LogFactory { static LogFactory logFactory = new SLF4JLogFactory(); }
PS:就问你尴尬不?底层new的是SLF4JLogFactory
5.4、总结
桥接jar就一招:偷梁换柱。jar包名都一样,只是做了个适配。
三、使用其他日志框架
1、使用其他日志框架
若我们使用的是非logback+slf4j的框架,则需要将此依赖移除掉,比如我们用的是log4j2
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> <exclusions> <exclusion> <artifactId>spring-boot-starter-logging</artifactId> <groupId>org.springframework.boot</groupId> </exclusion> </exclusions></dependency><dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-log4j2</artifactId></dependency>
2、疑问
问:SpringBoot底层是Spring,而Spring依赖的是commons-logging,那么SpringBoot没有剔除掉commons-logging吗?
答:当然剔除了!如下:
spring-boot-starter.pom
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-logging</artifactId></dependency><dependency> <groupId>org.springframework</groupId> <artifactId>spring-core</artifactId> <exclusions> <exclusion> <groupId>commons-logging</groupId> <artifactId>commons-logging</artifactId> </exclusion> </exclusions></dependency>
问:为什么一定要剔除掉呢?
答:我们上面分析过桥接jar,看到里面只是偷梁换柱,包名字都没换,这样一来,你在引入一个同包名的jar,不就冲突了吗?
3、总结
SpringBoot能自动适配所有的日志,而且底层使用slf4j+logback的方式记录日志,引入其他框架的时候,只需要把这个框架依赖的日志框架排除掉即可。
作者:编程界的小学生
链接:https://www.jianshu.com/p/639607b064f5