- 容器在启动的过程中会实例化org.springframework.context.ApplicationListener的实现类,其中包括org.springframework.boot.context.logging.LoggingApplicationListener
- LoggingApplicationListener通过监听容器的生命周期事件来实例化和配置org.springframework.boot.logging.LoggingSystem对象的。
-
抽象类LoggingSystem指定了日志相关实例的生命周期和默认支持的日志框架。
/** * 其支持默认支持Logback,Log4J,JavaLogging */ public abstract class LoggingSystem { /** * 返回用户指定使用的或者默认的LoggingSystem, * 默认返回LogbackLoggingSystem */ public static LoggingSystem get(ClassLoader classLoader) { String loggingSystem = System.getProperty(SYSTEM_PROPERTY); if (StringUtils.hasLength(loggingSystem)) { if (NONE.equals(loggingSystem)) { return new NoOpLoggingSystem(); } return get(classLoader, loggingSystem); } return SYSTEMS.entrySet().stream() .filter((entry) -> ClassUtils.isPresent(entry.getKey(), classLoader)) .map((entry) -> get(classLoader, entry.getValue())).findFirst() .orElseThrow(() -> new IllegalStateException( "No suitable logging system located")); } }
-
LoggingApplicationListener来调用LoggingSystem相关生命周期方法
public class LoggingApplicationListener { //确定了具体使用哪个日志框架,默认使用Logback private void onApplicationStartingEvent(ApplicationStartingEvent event) { this.loggingSystem = LoggingSystem .get(event.getSpringApplication().getClassLoader()); this.loggingSystem.beforeInitialize(); } //对LoggingSystem进行初始化 private void onApplicationEnvironmentPreparedEvent( ApplicationEnvironmentPreparedEvent event) { if (this.loggingSystem == null) { this.loggingSystem = LoggingSystem .get(event.getSpringApplication().getClassLoader()); } initialize(event.getEnvironment(), event.getSpringApplication().getClassLoader()); } //将LoggingSystem注册到容器中 private void onApplicationPreparedEvent(ApplicationPreparedEvent event) { ConfigurableListableBeanFactory beanFactory = event.getApplicationContext() .getBeanFactory(); if (!beanFactory.containsBean(LOGGING_SYSTEM_BEAN_NAME)) { beanFactory.registerSingleton(LOGGING_SYSTEM_BEAN_NAME, this.loggingSystem); } } //做一些清理相关的工作 private void onContextClosedEvent() { if (this.loggingSystem != null) { this.loggingSystem.cleanUp(); } } }
-
Springboot中使用Logback框架进行日志打印,其配置文件是如何支持springProperty标签的?
LogbackLoggingSystem在初始化的过程中会加载相关的xml配置文件,
通过logback相关的解析器进行解析,并对解析器进行来扩展(SpringBootJoranConfigurator),使其支持pringProperty标签。SpringBootJoranConfigurator 中定义了扩展的标签和对该标签的解析方式
class SpringBootJoranConfigurator extends JoranConfigurator { private LoggingInitializationContext initializationContext; SpringBootJoranConfigurator(LoggingInitializationContext initializationContext) { this.initializationContext = initializationContext; } @Override public void addInstanceRules(RuleStore rs) { super.addInstanceRules(rs); Environment environment = this.initializationContext.getEnvironment(); rs.addRule(new ElementSelector("configuration/springProperty"), new SpringPropertyAction(environment)); rs.addRule(new ElementSelector("*/springProfile"), new SpringProfileAction(this.initializationContext.getEnvironment())); rs.addRule(new ElementSelector("*/springProfile/*"), new NOPAction()); } }