SpringBoot-04 | spring-boot-starter-logging原理原理
第一步:springboot加载factories文件
读取的spring.factories里面所有的ApplicationListener,然后保存到listeners成员变量里面去备用。
public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
***
setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
this.mainApplicationClass = deduceMainApplicationClass();
}
打开autoconfigure的jar包,找到spring.factories,搜索logging:
打开ConditionEvaluationReportLoggingListener,看不出用了哪个log框架的实现,继续看一下pom的依赖,logback是springboot默认使用的日志框架。
打开jar包,不出所料,空空如也,他是作为一个Starter依赖包存在,它主要用于管理和集成日志框架(如Logback、Log4j2等)以及配置日志记录功能,具体看下pom即可。
Starter的作用就是导入其他包,springboot框架来实现这些包。
<?xml version="1.0" encoding="UTF-8"?>
******
<dependencies>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.12</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-to-slf4j</artifactId>
<version>2.17.2</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>jul-to-slf4j</artifactId>
<version>1.7.36</version>
<scope>compile</scope>
</dependency>
</dependencies>
</project>
第二步:构造监听器
EventPublishingRunListener加载springboot定义的监听器,并将log接口实现埋进去。
public ConfigurableApplicationContext run(String... args) {
***
SpringApplicationRunListeners listeners = getRunListeners(args);
***
}
getRunListeners从spring.factories继续读取SpringApplicationRunListener.class的配置类,默认值配置了唯一的一个EventPublishingRunListener,很显然是来做事件发布的,因为此时Spring环境还没有构建出来,Spring的那一套事件机制还无法使用,SpringBoot只好自己又搞了一个。
private SpringApplicationRunListeners getRunListeners(String[] args) {
Class<?>[] types = new Class<?>[] { SpringApplication.class, String[].class };
return new SpringApplicationRunListeners(logger,
getSpringFactoriesInstances(SpringApplicationRunListener.class, types, this, args),
this.applicationStartup);
}
--spring.factories # Run Listeners
org.springframework.boot.SpringApplicationRunListener=\
org.springframework.boot.context.event.EventPublishingRunListener
这里拿到了EventPublishingRunListener以后,然后又封装进了SpringApplicationRunListeners里面,同时还传进去一个log对象。注意这里的logger此时还是org.apache.commons.logging这个包下面的log。
class SpringApplicationRunListeners {
private final Log log;
private final List<SpringApplicationRunListener> listeners;
private final ApplicationStartup applicationStartup;
SpringApplicationRunListeners(Log log, Collection<? extends SpringApplicationRunListener> listeners,
ApplicationStartup applicationStartup) {
this.log = log;
this.listeners = new ArrayList<>(listeners);
this.applicationStartup = applicationStartup;
}
***
}
第三步:注册监听器到Spring中
把一开始从spring.factories中拿到的所有的ApplicationListener注册到了initialMulticaster里面,显然这里面也包括了我们今天要说的主角LoggingApplicationListener。
public ConfigurableApplicationContext run(String... args) {
***
listeners.starting(bootstrapContext, this.mainApplicationClass);
***
}
class SpringApplicationRunListeners {
void starting(ConfigurableBootstrapContext bootstrapContex