看一下spring boot如何一步一步地初始化Logback

前言

本文基于spring boot 3.0.2版本进行分析。

源码位置

既然是分析spring boot初始化logback部分的源码实现,第一步肯定是要找到源码在哪个位置,如下:

在这个logback包下面就是具体的实现。

初始化

spring boot的logging模块是随spring boot启动的时候就进行初始化,毕竟日志模块要尽可能早的进行初始化,至少要比其它功能模块初始化的早。

方法调用栈

借助idea的debug,通过方法调用栈来查看logback初始化的调整流程:

画蓝框的地方表明这是发布了一个ApplicationEnvironmentPreparedEvent事件,回调相关的监听器的时候执行的初始化动作:

java 复制代码
public void environmentPrepared(ConfigurableBootstrapContext bootstrapContext,  
ConfigurableEnvironment environment) {  
multicastInitialEvent(  
new ApplicationEnvironmentPreparedEvent(bootstrapContext, this.application, this.args, environment));  
}

监听器

日志初始化的代码入口类在LoggingApplicationListener,根据上面的调用栈也可以看到是监听到ApplicationEnvironmentPreparedEvent事件的时候才进行后续的初始化动作:

那么问题来了,LoggingApplicationListener这个监听器是如何被spring boot实例化的。 关键在于spring.factories,如下:

spring core下提供了SpringFactoriesLoader类,用于加载每个jar包下META-INF/spring.factories文件,当我们启动spring boot项目,在main方法中调用SpringApplication.run(Application.class, args)方法时候,会构造SpringApplication实例,在SpringApplication初始化SpringApplication的构造方法中,加载所有的ApplicationListener,如下:

LoggingApplicationListener因此被初始化。

为什么默认初始化Logback

在前面的部分提到了,Logback的初始化的源码在logging包下,但是logging包下包含了3种日志实现,为什么默认初始化logback呢,下面分析下:

这里的关键还在于spring.factories:

再看下前面提到的LoggingApplicationListener监听器的监听事件处理,在项目启动的时候,发布ApplicationEnvironmentPreparedEvent事件之前,会先发布一个ApplicationStartingEvent事件:

在这里进行日志系统的初始化:

因为调用到DelegatingLoggingSystemFactory类的getLoggingSystem方法:

可以看到只要获得一个LoggingSystemFactory实例就返回了,而Logback下的实现是默认排在第一位的,因此默认初始化Logback。

初始化配置

日志系统初始化的时候会加载配置文件进行初始化,代码位置及调用栈如下:

这里会先尝试加载logback本身的配置文件:

java 复制代码
protected String[] getStandardConfigLocations() {  
    return new String[] { "logback-test.groovy", "logback-test.xml", "logback.groovy", "logback.xml" };  
}

如果这几类配置文件都不存在,会开始查找自spring类型的配置:

java 复制代码
protected String[] getSpringConfigLocations() {  
    String[] locations = getStandardConfigLocations();  
    for (int i = 0; i < locations.length; i++) {  
        String extension = StringUtils.getFilenameExtension(locations[i]);  
        locations[i] = locations[i].substring(0, locations[i].length() - extension.length() - 1) + "-spring."  
+ extension;  
    }  
    return locations;  
}

根据源码其实可以看到就是logback的配置文件里后续加上-spring,比如logback-spring.xml,经常开发的同学应该都知道。 加载完配置文件,下面的初始化代码就没有比较特别的地方了,就是logback的初始化流程了:

当然,如果没有任何配置文件,最后就会采用默认的初始化配置:

默认的话,如果不指定日志文件:日志就只会输出到控制台了,下面这两个任选一:

如果没有配置上面这两个选项的任何一个,logFile是空的,就只会输出日志到控制台:

相关推荐
哦虎!3 小时前
【JavaEE】网络初识
java
for_ever_love__3 小时前
MySQL ORDER BY 排序优化:从 Using filesort 到索引有序扫描(含双路 / 单路排序原理)
java·mysql·优化·存储·by·order·filesort
我是人✓4 小时前
Java文件上传三方式对比:从传统到SpringBoot
java·开发语言
欣栀♡4 小时前
JVM 频繁 Full GC 先看日志括号里的 cause,jstat 的 FGC 在 JDK 8 上会骗人
java·jvm
IT研究室4 小时前
最新计算机毕业设计选题推荐-基于spring boot的葡萄酒文化宣传网站-网站-文档指导-Java-springboot
java·spring boot·课程设计
慧都小项5 小时前
MyEclipse 中创建和测试 JAX-RS REST 接口:从项目配置到 REST Explorer
java·restful·myeclipse·jax-rs
Wang's Blog5 小时前
Java 项目实战: 交友项目 - 入门案例:编写 Dubbo 服务提供者
java·dubbo·交友
秋饼5 小时前
Spring AI 2.0 结构化输出企业级实战:从 BeanOutputConverter 源码到生产级解析容错
java·ai·技术分享·后端开发
摇滚侠5 小时前
《计算机是如何工作的:人人都能懂的计算机软硬件工作原理》第 9 章 机器码与汇编语言 阅读笔记 9
java·开发语言·笔记
Cc.Y5 小时前
Java零基础入门:深入Java核心:文件IO与序列化全解
java·开发语言·python