SpringBoot对日志的配置和加载进行了封装,让我们可以很方便地使用一些日志框架,只需要定义对应日志框架的配置文件,比如LogBack、Log4j、Log4j2等,代码内部便可以直接使用。
比如我们在resources目录下定义了一个logback.xml文件,文件内容是logback相关的配置,然后就可以直接在代码在使用Logger记录日志啦。
下图是SpringBoot对日志功能的封装:
LoggingSystem内部结构
从图中也可以发现目前SpringBoot支持4种类型的日志,分别是JDK内置的Log(JavaLoggingSystem)、Log4j(Log4JLoggingSystem)、Log4j2(Log4J2LoggingSystem)以及Logback(LogbackLoggingSystem)。
LoggingSystem是个抽象类,内部有这几个方法:
- beforeInitialize方法:日志系统初始化之前需要处理的事情。抽象方法,不同的日志架构进行不同的处理
- initialize方法:初始化日志系统。默认不进行任何处理,需子类进行初始化工作
- cleanUp方法:日志系统的清除工作。默认不进行任何处理,需子类进行清除工作
- getShutdownHandler方法:返回一个Runnable用于当jvm退出的时候处理日志系统关闭后需要进行的操作,默认返回null,也就是什么都不做
- setLogLevel方法:抽象方法,用于设置对应logger的级别
AbstractLoggingSystem抽象类继承LoggingSystem抽象类,进行了一些扩展,重点在于initialize方法:
- 实现了beforeInitialize方法,但是内部不做任何处理
- 复写了initialize方法,具体过程如下
1 |
|
以LogbackLoggingSystem类为例,分析具体的初始化过程。
1 | // LogbackLoggingSystem.class |
LoggingSystem的初始化
LoggingApplicationListener是ApplicationListener接口的实现类,会被springboot使用工厂加载机制加载:
1 | // spring-boot-version.jar/META-INF/spring.factories |
1 | // SpringApplication.class |
spring-boot-starter模块内部会引用spring-boot-starter-logging模块,这个starter-logging模块内部会引入logback相关的依赖。这一依赖会导致LoggingSystem的静态方法get获取LoggingSystem的时候会得到LogbackLoggingSystem。
因此默认情况下,springboot程序基本都是使用logback作为默认的日志。
一些例子
前提都是以LogbackLoggingSystem作为日志系统。
项目里没有任何日志的配置
由于没有任何配置,进行initialize的时候日志配置文件为null,最后只能调用loadDefaults方法进行加载,LogbackLoggingSystem的loadDefaults方法,由于logFile为null,所以最终只构造了一个ConsoleAppender。
所以项目没有任何日志配置的情况下,控制台依旧能打印出项目的启动信息。
项目里没有任何logback的配置,只有yaml中配置了logging.file和logging.path
logging.file和logging.path的配置在LogFile这个日志文件类中生效。
比如yaml配置如下(只定义了logging.file):
1 | logging: |
这个配置导致了调用initialize方法的时候logFile存在,这样不止有ConsoleAppender,还有一个FileAppender,这个FileAppender对应的文件就是LogFile文件,也就是 /tmp/temp.log日志文件。
比如yaml配置如下(只定义了logging.path):
1 | logging: |
这个时候FileAppender对应的file是/tmp/spring.log文件。
1 | // LogFile.class |
所以我们如果配置了logging.path和logging.file,那么生效的只有logging.file配置。
resources下有logback.xml配置(相当于就是classpath下存在logback.xml文件)
之前分析过,LogbackLoggingSystem中的getStandardConfigLocations方法返回以下文件:
- logback-test.groovy或者logback-test-spring.groovy
- logback-test.xml或者logback-test-spring.xml
- logback.groovy或者logback-spring.groovy
- logback.xml或者logback-spring.xml
在resources目录下定义logback-spring.xml文件,内容如下:
1 | "1.0" encoding="UTF-8" xml version= |
这时logging.file配置失效,这是因为没有调用loadDefaults方法(loadDefaults方法内部会把LogFile构造成FileAppender),而是调用了loadConfiguration方法,该方法会根据logback.xml文件中的配置去构造Appender。
resources下有my-logback.xml配置
由于LogbackLoggingSystem中没有对my-logback.xml路径的解析,所有不会被识别,但是可以在yaml中配置logging.config配置:
1 | logging: |
这样配置就能识别my-logback.xml文件。
其它
最新版的SpringBoot内部提供了一个NoOpLoggingSystem,这个日志系统内部什么都不做,构造过程如下:
1 | public static LoggingSystem get(ClassLoader classLoader) { |
所以程序启动的时候加上 -Dorg.springframework.boot.logging.LoggingSystem=none就可以构造NoOpLoggingSystem这个日志系统。