📣 大家好,我是Zhan,一名个人练习时长两年的大三后台练习生🏀
📣 这篇文章是 Java 日志框架 的第一篇学习笔记📙
📣 如果有不对的地方,欢迎各位指正🙏🏼
📣 以始为终 —— Just do it! 🫵🏼🫵🏼🫵🏼
👉引言
如何理解《阿里巴巴 Java 开发手册》
中的 门面模式的日志框架,以及它如何做到处理方式的统一?
其实 Java 日志框架是有它的生态的:SLF4J 本身不提供日志的实现,Logback 给 SLF4J 提供门面的支持,也就是说日志框架是分为 门面框架 和 实现框架,他们之间又是怎么实现的呢,本文将会告诉你答案。
一、门面框架和实现框架
有点类似于接口和实现类的关系,门面框架和实现框架其实就是这样的关系:提供通用的日志 API 给调用方,而自己去实现不同日志框架的适配,这种设计模式叫做 外观模式,MySQL 的驱动设计其实也是这种思想
了解了日志框架的基本思想之后,就可以方便我们构造知识体系,究竟哪些框架是门面框架、哪些是实现框架:
🚪 门面框架
- 它本身不提供日志实现,仅仅提供“门面”,这点我们可以从它的名字中得到:
- Simple Logging Facade For Java(Java 的简单日志门面)
- 对应的日志实现框架:
Log4j、Logback、JUL……
- 通常与
Apache Log4j 1.x
结合使用
🔑 实现框架
- 它是 Java 标准库中自带的 API,只能进行简单的日志记录
- 也就是说它是一个简单“实现框架”,它并没有所谓的门面框架,也就是开发人员可以直接使用 JUL 提供的日志记录API
- 它存在两个版本——
log4j1 log4j2
Log4j1
不需要显示的门面支持,但是可以和Apache Commons Logging
结合使用,以提供门面的支持Log4j2
通常与SLF4J
结合使用,也就是SLF4J
的实现框架
- 它是
SLF4J
的实现框架,同样也是我们通常使用的组合,因为它们提供了良好的性能和灵活性
🎯 注意点
尽管日志门面框架提供给通用的日志 API 给调用方,但是这是不包括每个日志实现框架的配置
也就是说日志门面框架可以帮助我们使用统一使用 API,但是选用对应的实现框架也要配置对应的文件
二、SLF4J 是怎么实现它的“门面”的?
尽管我们了解了什么是门面框架,什么是实现框架,类比一下接口和实现类就能很好理解,但是它是怎么实现这个 外观模式 的呢?
我们可以看一下这张图,图中的绿框就是我们使用的 Spring 程序,而剩下的部分:
-
Spring程序默认使用 JCL 框架(图中的 Commons Logging API 也就是浅蓝色部分)
-
JCL 框架还可以和 Log4j1 一同使用(图中的灰色部分)
-
还有可以直接在程序中打印的 JUL 工具类(图中的灰色部分)
也就是说 Spring 这个 Application 会产生这三类日志。
而我们想使用 LogBack 作为实现框架,这就不免产生了一些冲突,SLF4J 是怎么做的呢?
- JCL 门面框架:可以引入
jcl-over-slf4j
,也就是 JCL 桥接器,它会把 JCL 的日志消息重定向到 SLF4J,从而让 SLF4J接管这些日志信息 - Log4j1:使用
jcl-over-slf4j
库,把调用 Log4j 打印日志的地方适配成 SLF4J 的API - JUL:同样是这个库,实现自定义的处理器,把 JUL 打印日志的地方进行适配的处理
我们如果使用 LogBack 作为日志的实现框架,也就是图中的蓝色部分:
注意:而如果我们使用 LogBack 作为实现框架,LogBack 的库中,内置了对 SLF4J 框架的实现,也就是实现了 SLF4J 提供的标准,因此可以直接调用
三、SpringBoot 日志框架的封装
Spring 采用 JCL 日志门面框架来记录日志,而 SpringBoot 保持和 Spring 一致,但是它提供了对 JUL、Log4j2、LogBack 日志实现框架的封装,提供默认的日志配置,我们可以从下面这个例子中证明上述的观点:
我们每次在启动 SpringBoot 项目的时候都会有这一信息:
2019-12-29 17:24:57.935 INFO 97606 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port(s): 8080 (http) with context path ''
2019-12-29 17:24:57.938 INFO 97606 --- [ main] c.i.s.lab36.prometheusdemo.Application : Started Application in 2.624 seconds (JVM running for 3.228)
2019-12-29 17:24:58.412 INFO 97606 --- [on(4)-127.0.0.1] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring DispatcherServlet 'dispatcherServlet'
其实这个日志是通过 LogBack 打印出来的,为什么这么说呢,在 DefaultLogbackConfiguration
中,定义了日志的格式,也就是说 SpringBoot 做了默认的 LogBack 的配置:
private static final String FILE_LOG_PATTERN = "%d{${LOG_DATEFORMAT_PATTERN:-yyyy-MM-dd HH:mm:ss.SSS}} "
+ "${LOG_LEVEL_PATTERN:-%5p} ${PID:- } --- [%t] %-40.40logger{39} : %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}";
也就是:日期 + 日志级别 + 进程ID + 线程名 + 源类 + 日志内容
而这些日志的配置是可以通过配置文件进行配置的:
logging.pattern.file
:文件的日志格式logging.pattern.console
:控制台的日志格式logging.pattern.dateformat
:日期和时间。logging.pattern.level
:日志级别。logging.pattern.pid
: 进程 ID。
配置文件指的是 application.yml 吗?其实不然,配置文件其实是不同的日志实现框架拥有不同的配置文件名称,可以理解为各个框架和Spring约定俗成:
- LogBack:
logback-spring.xml
、logback.xml
- Log4j2:
log4j2-spring.xml
、log4j2.xml
- JUL:
logging.properties
SpringBoot 中集成了这么多日志的框架,其中主要就是两种实现日志的方式,而我们选用的方式就是通过日志相关的 Starter 进行选用:
spring-boot-starter-logging
:使用 SLF4J + Logback 的组合spring-boot-starter-log4j2
:使用 SLF4J + Log4j2 的组合。
而我们默认情况下会使用 SLF4J + LogBack 的组合
💬 总结
本文主要讲解了 Java 中日志框架的生态:实现框架、门面框架,可以类比接口和实现类,而需要注意的是,尽管使用了门面框架,还是需要对实现框架进行配置,门面框架只是统一了 API。
如果说在看这篇文章之前,还分不清 SLF4J、Log4j、LogBack 这些日志框架,相信看完本文你能知道它们各自的使用场景和特点。
而对于 SLF4J 这个最常用且出名的门面框架,我们讲解了它对 JUL、Log4j1、JCL
框架的兼容的方式。
最后简单了解了一下 SpringBoot 日志框架的使用以及一些简单的配置,而下一篇文章我们会详细介绍 SpringBoot 的日志使用,敬请期待!
🍁 友链
- 芋道 Spring Boot 日志集成 Logging 入门
- Log4j Bridge (slf4j.org)
- 外观模式 | 菜鸟教程 (runoob.com)
- 如何优雅地记录操作日志? - 美团技术团队 (meituan.com)
- (二)日志规约 - 阿里巴巴Java开发手册 (oschina.io)
✒写在最后
都看到这里啦~,给个点赞再走呗~,也欢迎各位大佬指正以及补充,在评论区一起交流,共同进步!也欢迎加微信一起交流:Goldfish7710。