概述
在项目开发中,移动不能省略的就是日志,有了日志,你就能更快更方便了解处理过的数据和监控程序的运行状况。试想,如果没有现成的日志系统,你要如何打印日志?
控制台输出
你可以考虑将日志通过标准输出打印出来,一般系统都提供的标准输出和错误输出,但是除了潜在的性能问题之外,本身这种方式不够灵活,系统提供的输出流也难以做精确控制。
文件输出
你可以将日志写入文件系统,但是你要考虑很多业务之外的东西了,比如文件的路径,比如写日志的性能,文件是否要切分,写之前先确保日志文件被创建、如何做到日志文件和程序解藕。。。有太多细节需要考虑,并且你还需要确保代码健壮性。很显然,这并不简单。
java日志概述
以下不会涉及日志库的具体使用
有了上述的问题,必要需要解决的办法,在java世界里,存在形形色色的日志库,但是整体可大致分为以下几种
1.J.U.L
java.util.logging API,是JDK自带的一套日志库,使用率并不高,并非java日志首选,原因很简单,出来的时间不够早,java1.4才有,而且本身的设计也不够优秀,一般不使用,即使使用也是最终兜底方案。
2.slf4j和logback
slf4j本质上不是一个日志库,仅仅是一个日志门面,全称 Simple Logging Facade For Java。
logback就是slf4j的其中一个实现。
slf4j出现的原因是市面上有太多的日志库,并且各有优点。而日志库可以抽象像通用的Logger-Layout-Appender模式。为了能达到灵活的效果,slf4j只提供通用的logger层,各个业务和代码应该只对logger层有依赖,具体使用时搭配具体的Logger实现(Layout-Appender)。推荐在业务中使用slf4j。并且搭配logback使用。
3.log4j 1.x
log4j1.x在很多旧项目中有大量使用,作为一个整体库,也缺乏较好的设计,没有使用上述的分层设计,但是奠定了java日志库的基本模型。不推荐在新的项目中使用。事实上log4j 1.x和slf4j、logback的作者都是同一个人。
4.log4j2
log4j2也有大量的项目在使用,也使用了分层的设计模式。但是由于经常出安全问题,使用的频率也越来越低。不推荐使用。但是作为分层的设计,提供了log4j2-api。完全可以将实现层桥接到其他实现上。
5.各种桥接库
由于上述的分层设计,诞生了很多中间桥接库。甚至有将log4j1.x桥接到log4j2-api上从而使用其他实现的操作。本质上不承担具体日志功能。
代码分析
sprign-boot版本:2.2
spring-boot日志
接下来我们分析spring-boot的日志是怎样的设计,从上年的了解的信息可知,目前,实际的日志实现主要是J.U.L和logback还有log4j2。spring-boot提供了自动装配的能力,仅需要提供对应的依赖就能激活响应的日志配置,看起来很“智能”,但是我们知道,没有那么多智能的事,只是有人替我们做了处理。理解了spring-boot log的配置,我们就能很好解决开发中遇到的问题。
日志实现
首先在spring-boot的org.springframework.boot.logging包下,是spring的内部日志实现,包含了对logback和log4j2以及jul的配置。
日志启动入口
spring中存在很多事件,log的配置就由某些特定的事件触发。
org.springframework.boot.context.logging.LoggingApplicationListener是事件监听类,该类通过spring spi的方式被加载到容器中,成为内置的消费者,消费事件后,调用LoggingSystem的get方法出发内部选择。
LoggingSystem内维护了一组map
上述可知,建立了每个日志库内核心类名和对应的LoggingSystem实现的对应关系。
接下来进行LoggingSystem的选择
LoggingSystem选择实现的过程this.loggingSystem = LoggingSystem.get(event.getSpringApplication().getClassLoader());
选择的过程是,首先通过加载map的key,也就是日志库内核心类,看能否加载类成功,如果能加载成功就能判断项目使用的日志库,并且调用LoggingSystem对应的实现类的构造方法,完成日志库的初始化和配置。
这个过程我们也能看出来,具体的日志库的选择顺序,优先logback,其次log4j2,最后jul,并且初始化最高优先级的配置之后,不会初始化其他选项。
spring-boot对logback的自定义设置
标准的logback使用的配置按优先级为
"logback-test.groovy", "logback-test.xml", "logback.groovy", "logback.xml"
对应的代码是
默认的logback配置文件而spring-boot中,则是
"logback-test-spring.groovy", "logback-test-spring.xml", "logback-spring.groovy", "logback-spring.xml"
对应的代码如下,可以看到,spring-boot中推荐的日志文件的命名是在标准配置文件的名称后面固定加“-spring”,这个代码解释了为什么是这样的规则。
spring指定配置文件的名称并且优先顺序为优先加载标准配置,如果有默认配置,不使用spring-boot自定义的。
spring-boot专用标签
spring-boot中,使用logback的xml配置增加了几个专用标签。原因是初始化类是SpringBootJoranConfigurator而非默认的JoranConfigurator,内部增加了几个标签处理类,是spring扩展了默认的标签处理器
总结
通过上述的分析,我们能理解了为什么在spring-boot中使用日志跟直接使用logback为什么存在一些差异的原因,这些有助于我们更好的打印我们的日志和解决实际开发过程中出现的问题。
网友评论